JVM
类加载器(ClassLoader)
Bootstrap ClassLoader
- $JAVA_HOME中jre/lib/rt.jar里所有的class或Xbootclasspath选项指定的jar包
Extension ClassLoader Person
- 加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包
App ClassLoader
- 加载classpath中指定的jar包及Djava.class.path所指定目录下的类和jar包
Custom ClassLoader
- 通过java.lang.ClassLoader的子类自定义加载class,属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader
双亲委派机制
- 防止重复加载同一个.class。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。
- 保证核心.class不能被篡改。通过委托方式,不会去篡改核心.clas,即使篡改也不会去加载,即使加载也不会是同一个.class对象了。不同的加载器加载同一个.class也不是同一个Class对象。这样保证了Class执行安全。
运行时数据区
方法区
- 类信息、常量、静态变量、即时编译器编译后的代码等数据。
堆
- Java对象实例以及数组都在堆上分配
虚拟机栈
-
局部变量表
-
操作数栈
- 局部变量表或对象实例的字段中复制常量或变量写入到操作数栈,再随着计算的进行将栈中元素出栈到局部变量表或者返回给方法调用者
-
动态链接
- 在一个class文件中,一个方法要调用其他方法,需要将这些方法的符号引用转化为其在内存地址中的直接引用,而符号引用存在于方法区中的运行时常量池。
-
方法出口
本地方法栈
程序计数器
- 当前线程所执行的字节码的行号指示器
Java对象的内存布局
对象头(Header)
-
Mark Word
-
用于存储对象自身的运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。
- 64位系统:8字节
-
-
类型指针
-
指向对象对应的类型元数据的内存地址
- 64位系统:8字节
-
-
数组对象特有
-
数组长度
- 4字节
-
实例数据(Instance Data)
-
包含了对象的所有成员变量,大小由各变量类型决定
-
boolean、byte
- 1字节
-
short、char
- 2字节
-
int
- 4字节
-
long
-
子主题 5
-
对齐填充(Padding)
JVM内存模型
方法区
- 永久代(JDK1.7之前)Perm Space
- 元空间(JDK8之后)MetaSpace
堆
-
老年代 Old区
-
新生代 Young区
-
Eden区
-
Survivor区
- S0
- S1
-
GC
判断一个对象是否是垃圾?
-
引用技术法
-
可达性分析法
-
GC Root的条件
- 类加载器
- Thread
- Java虚拟机栈中的局部变量表
- 本地方法栈中的局部变量表
- static(方法区)等
-
什么时候会回收垃圾?
-
System.gc()
- 只是发出一个信号,什么时候回收由JVM决定
-
新生代不够用了
- Young GC
-
老年代不够用了
- Old GC
-
永久代不够用了
- Metaspace GC
怎么回收?
-
标记清除
- 耗时(需要扫描整个内存空间),内存碎片
-
标记整理
- 整理非常耗时
-
标记复制
- 浪费一半的内存空间
垃圾收集器
-
Serial (标记复制)
- 单线程 Stop the world
-
Serial Old(标记整理)
- 单线程 Stop the world
-
ParNew
- 多线程
-
ParallelScanvenge
- 多线程
-
Parallel Old
-
CMS(老年代)标记清除
-
初始标记(单线程STW)
- 标记GC Root能够直接关联的对象
-
并发标记
- 进行GC Root间接关联
-
重新标记(多线程STW)
- 修改并发标记因为用户代码执行
-
并发清理
- 垃圾回收
-
-
G1
-
初始标记
-
并发标记
-
最终标记
-
筛选回收
- 停顿时间优先,停顿时间-初始标记时间-最终标记时间
-
-
ZGC(Zero GC)
- 可以达到10ms以内的停顿时间
- 支持TB级别的内存
- 堆内存变大停顿后停顿时间还是在10ms以内
如何选择垃圾回收器?
- 优先调整堆的大小来让服务器自己选择
- 如果内存小于100M,使用串行收集器
- 如果是单核,并且没有停顿时间要求,使用串行或者JVM自己选择
- 如果允许停顿时间超过1秒,选择并行或JVM自己选
- 如果响应时间最重要,并且不能超过1秒,使用并发收集器