性能文章>居然还有人找不到native方法,我来告你>

居然还有人找不到native方法,我来告你原创

3187021

哈喽,我就是Java圈最卷的硬核男人子牙。手撸过JVM、JMM、synchronized、线程池、NIO…

 

大家平时研究Java代码,比如想研究Java线程与操作系统线程之间的关系,是否总是被卡在native方法上,内心是否如图

 

 

今天我就教大家如何精准定位到Java方法对应的C++代码、如何高效研究Hotspot源码。

 

甚至!教大家如何修改Hotspot源码,拓展反射API,为我所用!

 

怎么找

 

就拿线程的start方法为例吧,找到它对应的native方法。

private native void start0();

 

一、定位文件

 

如果是系统的native方法,都是很有规律的

 

start0是Thread类中的方法,Thread类在jdk中有其对应的.c文件

  •  
/openjdk/jdk/src/share/native/java/lang/Class.c

 

 

有没有看到很多你熟悉的Java类?

 

比如System.c,里面的就是System.java中的所有native方法。

 

二、找方法

 

系统提供的JNI模块注册native方法有两种方式,所以找的话也有两种情况:

 

1、直接调用JVM模块中的方法,在每个.c文件的头部就可以找到

 

 

2、JNI模块中定义一个方法,直接找

 

 

3、你得理解这张远古图,才能理解JVM各模块的联系

 

 

怎么读

 

找到native方法对应的Hotspot源码是第一步,接下来就是如何读懂的问题。

 

Hotspot主要是用C++编写的,所以掌握C++是必要的。对于大家来说,C++最难的应该就是它丰富的语法糖及万恶之源指针了。这些知识,只能通过做项目才能熟练掌握及深入理解。

 

所以掌握C++是基础,你还得有C++的项目开发经验,否则你还是看不懂Hotspot源码。

 

做什么项目?肯定不是写写常见的数据结构及算法,你得写一些与Hotspot相关的小项目,比如OOP机制、内存池、垃圾收集算法…

 

掌握了C++,有C++项目开发经验就可以了吗?还不够!你还得对JVM底层原理有深入的理解。这个理解不是看周志明的《深入理解Java虚拟机》就足够的,你得去看一些讲Hotspot源码级别的书籍,做到真正的理解才足够。


这边给大家推荐两本:深入Hotspot、解密Java虚拟机底层原理与实现。如果你懒得找,关注公众号【硬核子牙】回复【Hotspot书】获取。

 

除此之外,还得掌握HSDB这款工具的使用,能熟练地用它去查找JVM内部找到你想要的数据。

 

比如静态属性到底是在堆区还是方法区这样的问题,就可以通过HSDB查看Java类映射的Klass对象,然后通过查看它的属性得到答案。

 

这款工具不知道怎么用?我之前讲的JVM底层原理中有演示。关注公众号【硬核子牙】回复【Hotspot书】获取。

 

 

再说下研究Hotspot源码的顺序:

  1. 先把JVM的启动流程整个看一遍,这时候会碰到很多不知道干啥有啥用的类、不知道为什么存在的流程…不用管,理清主线就可以了。

  2. 第二步就是去看JVM是如何执行main方法的,这个流程包含类加载的流程及JVM执行方法的流程,同样会遇到各种看不懂。不要灰心,理清主线了解个大概即可。

  3. 然后就是求甚解的阶段,基于对JVM底层原理的理解仔细读类加载流程、内存初始化、垃圾收集器与内存如何构建起的桥梁、模板引擎执行流生成、封装继承多态的实现原理…这个过程可能会很久很久,所以这个过程不能急,慢慢啃。

 

如果你对Hotspot源码感兴趣,想躺着研究,可以考虑加入我的手写JVM小班。我会把我在Hotspot上研究的心得循序渐进地分享给你。

 

读源码需要有单步调试环境,因为你需要看调用链路、变量赋值、指针指向,甚至是运行时代码区。我之前分享过如何搭建单步调试openjdk环境

 

相关的软件建议与我的环境保持一致,不然你可能需要花很长时间踩坑。关注公众号【硬核子牙】回复【单步调试】获取相关软件。

 

 

 

黑科技

 

native方法也找到了,我又是C++大佬,我该怎么验证我的想法及猜测呢?改代码呗!改完后给Java提供调用API呗!JNI行吗?不行!JNI能做的事情都被Hotspot限制死了。

 

你想做的一些事情,只有修改Hotspot源码这一招。我给大家分享一招最简单的。咱们就拓展反射的API吧。

 

一、增加native方法

 

 

二、实现native方法

 

 

三、让编译器知道我增加了方法

 

/openjdk/jdk/make/mapfiles/libjava/mapfile-vers# Define public interface.SUNWprivate_1.1 { global: …… Java_java_lang_Class_isInstance1; ……

 

四、编译

 

sudo make all DISABLE_HOTSPOT_OS_VERSION_CHECK=OK ZIP_DEBUGINFO_FILES=0

 

五、运行

 

 

OK,东风已就位,可以踏上探究Hotspot源码之旅了。

 

记得收藏哦,不然哪天想找代码,或者哪天膨胀了想改Hotspot源码…凉凉!

 

 

 

你好,我是子牙。十余年技术生涯,一路披荆斩棘从小白到技术总监到创业。技术栈如汇编、C语言、C++、Windows内核、Linux内核及特别喜欢研究虚拟机底层实现,对JVM有深入研究。分享的文章偏硬核,很硬的那种。不考虑交个朋友吗?关注硬核子牙

 

请先登录,再评论

暂无回复,快来写下第一个回复吧~

为你推荐

不起眼,但是足以让你有收获的JVM内存分析案例
分析 这个问题说白了,就是说有些int[]对象不知道是哪里来的,于是我拿他的例子跑了跑,好像还真有这么回事。点该 dump 文件详情,查看相关的 int[] 数组,点该对象的“被引用对象”,发现所
从一起GC血案谈到反射原理
前言 首先回答一下提问者的问题。这主要是由于存在大量反射而产生的临时类加载器和 ASM 临时生成的类,这些类会被保留在 Metaspace,一旦 Metaspace 即将满的时候,就会触发 Fu
关于内存溢出,咱再聊点有意思的?
概述 上篇文章讲了JVM在GC上的一个设计缺陷,揪出一个导致GC慢慢变长的JVM设计缺陷,可能有不少人还是没怎么看明白的,今天准备讲的大家应该都很容易看明白 本文其实很犹豫写不写,因为感觉没有
协助美团kafka团队定位到的一个JVM Crash问题
概述 有挺长一段时间没写技术文章了,正好这两天美团kafka团队有位小伙伴加了我微信,然后咨询了一个JVM crash的问题,大家对crash的问题都比较无奈,因为没有现场,信息量不多,碰到这类问题我
又发现一个导致JVM物理内存消耗大的Bug(已提交Patch)
概述 最近我们公司在帮一个客户查一个JVM的问题(JDK1.8.0_191-b12),发现一个系统老是被OS Kill掉,是内存泄露导致的。在查的过程中,阴差阳错地发现了JVM另外的一个Bug。这个B
JVM实战:优化我的IDEA GC
IDEA是个好东西,可以说是地球上最好的Java开发工具,但是偶尔也会卡顿,仔细想想IDEA也是Java开发的,会不会和GC有关,于是就有了接下来对IDEA的GC进行调优 IDEA默认JVM参数: -
不起眼,但是足以让你收获的JVM内存案例
今天的这个案例我觉得应该会让你涨姿势吧,不管你对JVM有多熟悉,看到这篇文章,应该还是会有点小惊讶的,不过我觉得这个案例我分享出来,是想表达不管多么奇怪的现象请一定要追究下去,会让你慢慢变得强大起来,
如何通过反射获得方法的真实参数名(以及扩展研究)
前段时间,在做一个小的工程时,遇到了需要通过反射获得方法真实参数名的场景,在这里我遇到了一些小小的问题,后来在部门老大的指导下,我解决了这个问题。通过解决这个问题,附带着我了解到了很多新的知识,我觉得