一.内存分配
1.非线程共享区
每个线程拥有一个,包含虚拟机栈、本地方法栈和程序计数器;
java栈的生命周期与该线程相同,故当线程终止该区域被释放.
本地方法栈用于保存native本地方法的变量及数据;
2.线程共享区
该区域包含堆内存和方法区,声明周期与程序运行的声明周期相同,gc的工作场所是在堆内存;
堆内存用于保存new出来的对象,方法取用于存放类信息,常量,静态变量,和即时编译器编译后的代码数据;
运行时常量池是方法区的一部分,存放编译期生成的各种字面常量和符号引用;
二.对象保存
对象在内存中布局可以分成三块区域:对象头、实例数据和对齐填充。
1.对象头
包括两部分信息:运行时数据和类型指针,如果对象是一个数组,还需要一块用于记录数组长度的数据。
1)类型指针:指向该对象的类元数据,虚拟机通过这个指针可以确定该对象是哪个类的实例。
2)运行时数据包括哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向锁ID和偏向时间戳等;
2.实例数据
就是在程序代码中所定义的各种类型的字段,包括从父类继承的,这部分的存储顺序会受到虚拟机分配策略和字段在源码中定义顺序的影响。
3.对齐填充
HotSpot的自动内存管理要求对象的起始地址必须是8字节的整数倍,即对象的大小必须是8字节的整数倍,对象头的数据正好是8的整数倍,所以当实例数据不够8字节整数倍时,需要通过对齐填充进行补全。
三.java程序运行过程
1.一个 Java 源程序文件,会被编译为字节码文件(以 class 为扩展名);
2.ClassLoader加载类:
Java语言系统自带有三个类加载器:
Bootstrap ClassLoader 最顶层的加载类,主要加载核心类库,%JRE_HOME%\lib下的rt.jar、resources.jar、charsets.jar和class等。另外需要注意的是可以通过启动jvm时指定-Xbootclasspath和路径来改变Bootstrap ClassLoader的加载目录。比如java -Xbootclasspath/a:path
被指定的文件追加到默认的bootstrap路径中。我们可以打开我的电脑,在上面的目录下查看,看看这些jar包是不是存在于这个目录。
Extention ClassLoader 扩展的类加载器,加载目录%JRE_HOME%\lib\ext目录下的jar包和class文件。还可以加载-D java.ext.dirs
选项指定的目录。
Appclass Loader也称为SystemAppClass 加载当前应用的classpath的所有类。
3.类加载过程