Java 语言最重要的特点之一: 跨平台应用,正是因为 JVM 的存在。想要 Java 开发稳步进阶,学 JVM 这条路绕不开。
1. 为什么要学 JVM?
咱们都晓得,要做 Java 开发,必须在你的电脑上装置 JDK 才行,装置 JDK 之后外面会有一个 JRE 的目录,JRE 提供了软件环境 —-JVM。
在开发过程中当咱们呈现内存透露、内存溢出的时候咱们不应该想到 -Xms 去设置或者栈的 -Xss 或者 restart 来解决,而是更应该去想想,为什么会呈现? 什么导致? 怎么优化?
2.JVM 是什么?
JVM,即 Java Virtual Machine,Java 虚拟机 运行在操作系统之上的虚构的计算机。咱们次要钻研的是 HotSpot VM JDK 自带的虚拟机,这个虚拟机有两个很好的长处:精确式 GC + 热点代码探测技术。所谓精确式 GC,就是让 JVM 晓得内存中某地位数据的类型什么。比方以后内存地位中的数据到底是一个整型变量还是一个援用类型。这样 JVM 能够很快确定所有援用类型的地位,从而更有针对性的进行 GC roots 枚举。JVM 进行一段代码是不是热点代码,是不是须要触发即时编译,这样的行为称为热点探测。Java 语言最重要的特点之一: 跨平台应用,正是因为 JVM 的存在。
3.JVM 虚拟机内存构造
JVM 虚拟机将其内存分为程序计数器、虚拟机栈、本地办法栈、java 堆、办法区。
咱们看看下面图片,当文件被加载之后,会变成一个 JVM 过程 而字节码文件就运行在 JVM 过程内。开启一个线程就独占一块内存区域,彼此独立。分区只思考线程平安问题,线程共享不平安,存在线程对于资源得抢夺。
4. 你真正理解办法区吗?
办法区实际上是属于共享内存区域,Java 源文件反映的信息都叫类信息,Java 源文件会被编译成二进制文件加载到 JVM 去执行。比方:要去拿类对象,通过 Student.class,类对象存在办法区,实际上拿到的是办法区的援用。
这里多提一点,办法区也存在垃圾回收,然而回收率低,回收次要针对常量池的回收,和类型卸载。当办法区无奈满足内存需要时,会报 OOM。
在共享区画堆内存,这个大家比拟理解了:
Student stu = new Student();
new 进去得对象存在堆外面,stu 是存在栈外面,这里提到的堆就是堆区。
对于绝大多数利用来说,这块区域是 JVM 所治理的内存中最大的一块。线程共享,次要是寄存对象实例和数组。外部会划分出多个线程公有的调配缓冲区(Thread Local Allocation Buffer, TLAB)。能够位于物理上不间断的空间,然而逻辑上要间断。
试想,堆中存储了对象,到底存的是什么?Java 对象在内存中的布局?
先运行 int num = 1; 不会存 num 的名称,而是存 1。而后是存 marsLee,不是名称,而是援用堆区的地址。
元信息保留在办法区,元信息 (模板) 在堆区都有实例存储。动态变量和办法都存在办法区。存储对象只是存储实例对象的值,名称不会存。
那对象怎么鉴定呢? 通过对象头 object header,蕴含 Mark Word(标记字段)和 Klass Pointer(类型指针)
✅Klass Pointer,即是对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。
✅Mark Word,用于存储对象本身的运行时数据,如哈希码(HashCode)、GC 分代年龄、锁状态标记、线程持有的锁、偏差线程 ID、偏差工夫戳等等。
5. 知识点总结
对象放堆区,线程安不平安? 不平安。
多个线程操作一个对象就会不平安,除非只读。
当多个线程拜访 Student 对象时,这个动态字段会不会平安? 不平安。