深入理解JVM3:内存结构篇(堆、本地方法栈)

1.本地方法栈

JNI即Java Native Interface(本地方法接口),它能在Java层实现对本地方法的调用,一般本地的实现语言主要是C/C++,其实从虚拟机层面来看JNI挺好理解,JVM主要使用C/C++ 和少量汇编编写,在执行Java字节码时如果遇到有某个方法标明为Native的则从JVM中找到对应的C/C++函数,一般本地方法对应的函数会被注册到JVM中。

使用JNI能让Java与本地语言交互,但一般也意味着丧失了跨平台性,而有些场合会使用。比如标准的Java特性不符合你的需求时,比如在性能要求很高的某段逻辑。


2.堆(Heap)的定义

定义:

    通过new关键字创建的对象都会使用堆内存

特点:

    有垃圾回收机制 它是线程共享的,堆中的对象都需要考虑线程安全问题

3.堆内存诊断工具(JVisualVM)


3.1.示例一:实时查看堆内存使用情况

运行上述代码,利用jvisualvm观察堆内存的变化(如下) 如上图:在时间点一时,因为程序没有做任何的操作,内存一致保持在17MB左右。到时间点二后,因为程序增加了一个byte[1024 * 1024 * 10]数组,即占用内存10MB的数组对象,所以堆内存增加了10MB到达27MB。最后来到时间点三,堆内存急速下降,因为在这里程序调用了GC即垃圾回收机制,对堆内存不再需要使用的对象进行清除,使得内存占用急剧下降到了3MB。


3.2.示例二:垃圾回收后,占用仍然高

运行上述代码在其运行时使用jvisualvm工具执行一次GC后内存变化如下 上述代码中:使用for循环生成了100个占用内存10MB的byte数组,并且将其存入到list数组当中,因此当for循环结束后,堆内存占用应该在1G左右。通过上图我们也可以知道具体是指是在1.1G,此时我们对其进行一次GC,发现堆内存只下降了0.1G,也就是说通过for循环生成的1Gbyte数组并没有被垃圾回收机制处理,因为此时byte数组已经被list引用,GC认为这些byte数组不是“垃圾”,所以不会对其进行回收。

这种情况可以在编码时开始考虑和处理,但程序猿往往都是没法将任何的程序 “一蹴而就” 的,总有些问题是在程序运行时才发现的,这时我们应该如何排查?

经验分享 程序员 微信小程序 职场和发展