一.JVM体系结构图
在整个JVM学习过程中,这张图要深深记住,这样才不会迷失方向
二.Native方法
在多线程Thread的start方法源码中,有一个方法【private native void start0()】,其中有一个关键字native。
- 凡是带了native关键字的,说明Java的作用范围达不到了,回去调用底层C语言的库。
- 会进入本地方法栈,调用本地方法接口JNI(Java native interface)
历史原因:Java诞生的时候是C、C++横行的时候,想要立足,必须调用C、C++的程序,于是就在内存中专门开辟了一块区域标记为native的代码,它的具体做法是在Navitive Method Stack中登记navtive方法,在执行引擎的时候加载Native Libraries。
三.方法区
方法区(Method Area)是被所有线程共享,所有定义的方法的信息都保存在该区域。
静态变量、常量、类信息(构造方法、接口定义)、运行时的常量池存在方法中,但实例变量存在堆内存中和方法区无关(static、final、class、常量池)
四.栈
- 用一种通俗的语言来解释就是:喝多了吐就是栈,吃多了拉就是队列。
- 栈的存储速度比堆要快,仅次于寄存器,栈数据可以共享。
- 栈不存在垃圾回收问题,只要线程一旦结束,该栈就Over,生命周期跟线程一致,是线程私有的。
五.堆(sun-hotspot)
一个JVM只有一个堆内存,堆内存的大小是可以调节的;类加载器读取了类文件后,需要把类、方法、常变量放到堆内存中,保存所有引用类型的真实信息。
5.1堆
- 新生区 Young/New
- 养老区 Tenure/Old
- 永久区 Perm
GC垃圾回收主要在新生区和养老区,又分为轻GC和重GC,如果内存不够,或者存在死循环,就会导致java.lang.OutOfMemoryError:Java heap space.
5.2新生区
新生区又分为两部分:伊甸区(Eden)和幸存区(Survivor Space),所有类都是在Eden区被new出来的。
当Eden的空间用完时,程序又要创建对象,JVM的垃圾回收器将对Eden区进行垃圾回收(Minor GC),类似操作0区满了,移动到1区,养老区。若养老区执行了Full GC后依然无法进行对象的保存,就会产生OOM异常“Out of MemoryError”。
若出现OOM,说明Java虚拟机的堆内存不够,原因如下:
- Java虚拟机的堆内存设置不够,可以通过参数 -Xms(初始值大小),-Xmx(最大大小)来调整
- 代码中创建了大量的对象,并且长时间不能被垃圾收集器收集或者死循环
5.3永久区
- 用于存放JDK自身所携带的Class,Interface的元数据,存储的是运行环境必须的类信息
- 此区域的数据是不会被垃圾回收器收掉的,关闭JVM才会释放此区域所占用的内存
- Java.lang.OutOfMemoryError:PerGen space说明Java虚拟机对永久代Perm内存设置不够
- JDK1.8及之后无永久代,常量池1.8在元空间
5.4堆内存调优
-Xms:设置初始分配大小,默认物理内存的1/64
-Xmx:最大分配内存,默认物理内存的1/4
-XX:PrintGCDetails:输出详细的GC处理日志
六.方法区+堆+栈交互
图解:https://blog.csdn.net/thera_qing/article/details/110544168
学习来自:B站-狂神说