自己乱捣鼓,乱总结一下关于JVM的重点,大白话写的。
- JVM的内存布局
- 对象的创建过程
- 垃圾回收
- 类加载过程
一、JVM内存布局
1、程序计数器
记录字节码指令运行到哪个地址,记录位置用的,不会存在栈溢出和内存溢出错误,属于线程私有的。
2、虚拟机栈
每执行到一个方法,会在虚拟机栈中开辟一个栈帧,也是线程私有,会存在栈溢出和内存溢出错误。
栈帧,用于存储:局部变量表、操作数栈、动态连接、方法出口等信息。
3、本地方法栈
本地方法栈和虚拟机栈作用差不多,区别是本地方法栈执行的是本地native方法,而虚拟机栈是为字节码中的Java方法服务的。
4、Java堆
堆是存放对象实例信息的地方,也是JVM内存模型中占用内存最大的区域,属于所有线程共享的区域,会出现内存溢出错误。
5、方法区
方法区用于存储已被JVM加载的类信息、常量、静态变量、即时编译器编译后的代码缓存等数据,也是所有线程共享的区域,会出现内存溢出错误。
注意JDK1.7和JDK1.8,在对方法区实现的区别。
二、对象的创建过程
JVM在Java堆中对象分配、布局和访问的全过程。
此章节中的对象仅为普通Java对象,不包括数组和Class对象。
1、对象的创建
- 当程序计数器执行到了new的字节码指令时,首先需要去检查这个指令后的参数能否在常量池中找到一个符号引用,并且判断这个符号引用的类是否已经被加载、验证、准备和解析过,若没有,则还需执行此流程。
- 确定改类被加载过后,就在Java堆中分配一块内存给改对象实例,并且对此对象实例进行必要的设置,比如确定该对象是哪个类的实例、元数据信息等。
- 最后进行<init>方法,根据程序员字节码的指令进行对象实例的初始化。
- 这时,一个真正可用的对象就被创造出来了。
2、对象的内存布局
一个对象实例分为三部分:
- 对象头:存储对象自身运行时所需要的数据信息。
- 实例数据:对象真正存储的有效信息。
- 对齐填充:没有实际作用,仅仅作为占位符。