JVM Notes
Posted on 14/10/20191JVM
Hotspot Architecture
Key HotSpot JVM Components
The key components of the JVM that relate to performance are highlighted in the following image.
There are three components of the JVM that are focused on when tuning performance. The heap is where your object data is stored. This area is then managed by the garbage collector selected at startup. Most tuning options relate to sizing the heap and choosing the most appropriate garbage collector for your situation. The JIT compiler also has a big impact on performance but rarely requires tuning with the newer versions of the JVM.
虚拟机调优目标
-
响应速度,追求快速响应,gc时的暂停不可接受。该类应用为:网页应用,桌面gui程序。
-
吞吐量,追求单位时间内完成的数据处理量最大化,可以接受gc时的暂停。该类应用为:批处理任务。
虚拟机调优对象
堆内存
堆内存结构:
垃圾回收算法
算法 | 特点 |
---|---|
标记-清除法(mark-sweep) | 标记出存活的对象,删除未引用对象。 1.效率问题,标记和清除都会耗费大量时间; 2.空间问题,易产生内存碎片。 |
复制法(copying) | 两块相同大小的内存区域,gc时,将一块内存中存活的对象拷贝到另一块内存中。实现简单、运行高效,缺点是空间利用率低 98%的对象都是“朝生夕死”,所以内存区域大小不必相等。HotSpot虚拟机新生代划分出3块区域不等的内存区,分别命名为Eden, Survivor0和Survivor1区,每次只使用Eden区和Survivor区的一个,整理出来的存活对象复制到未被使用的Survivor区,如此往复使用。HotSpot虚拟机的Eden区与Survivor区的比例为8:1,即内存利用率为90%。 |
标记-整理法(mark-compact) | 标记出存活对象后,将存活对象往一端移动,再将边界对象外对象清除。 |
分代法(generational collection) | 新生代对象存活率低,采用复制法将少数存活对象复制出来 老年代对象存活率高,内存空间分配小,采用标记-清理法或标记整理法 |
收集器名称 | 特点 | 收集算法 |
---|---|---|
serial | 新生代、单线程、stop the world、 | 停顿时间长 |
parnew | 新生代、多线程并行、stop the world、 | 与serial收集器的区别在于多线程并行垃圾回收 |
parallel scavenge | 新生代、多线程并行、stop the world、吞吐量优先、复制算法 | 尽可能缩短垃圾回收用户线程停顿时间 |
serial old | 老年代、单线程、stop the world | serial的老年代版本 |
parallel old | 老生代、多线程并行、stop the world、吞吐量优先 | paralle scavenge的老年代版本 |
cms(concurrent mark sweep) | 老年代、多线程并行、并发、部分stop the world、响应速度优先 | 停顿时间短,适用对响应要求高的应用,如:桌面gui程序,服务器应用。使用标记-清除算法,容易产生内存碎片,可以通过设置参数隔一段时间进行整理。 |
g1(garbage first) | 不分年代、多线程并行、并发、部分stop the world、响应速度优先、jdk1.7后开始,cms收集器的替代者。 | 停顿时间短,适用于对响应速度要求高的应用。 |
选项 | 描述 |
---|---|
-XX:+UseSerialGC | client模式下的默认值,使用serial + serial old 收集器 |
-XX:+UseParNewGC | 使用parnew + serial old收集器 |
-XX:+UseConcMarkSweepGC | 使用parnew + cms + serial old收集器,serial old收集器在cms出现concurrent mode failure时的备用收集器 |
-XX:+UseparallelOldGC | server 模式下的默认值,使用parallel scavenge + parallel old收集器 |
-XX:+UseG1GC | 使用garbage first 收集器 |
-XX:SurviorRatio | 新生代Eden 区与Survivor区的比例,默认值为8,eg:-XX:SurvivorRatio=8 |
-XX:PretenureSizeThreshold | 直接晋升到老年代的对象大小,eg:-XX:PretenureSizeThreshold=3145728 |
-XX:MaxTenuringThreshold | 晋升到老年代的对象年龄,eg:-XX:MaxTenuringThreshold=15 |
-XX:UseAdaptiveSizePolicy | |
-XX:+PrintGCDetails | 打印垃圾回收信息 |
-XX:Xms | 堆初始内存大小,eg:-XX:Xms10M,设置10M堆初始内存 |
-XX:Xmx | 堆最大内存大小 |
-XX:Xmn | 新生代内存大小 |
-XX:PermSize | 老年代内存大小 |
-XX:MaxPermSize | 老年代最大内存大小 |
内存分配策略
- 对象优先分配在Eden区
- 大对象直接进入老年代
- 长期存活对象进入老年代
- 动态判定对象年龄
- 空间分配担保
查看class文件
javap -verbose ClassName.class
xxd ClassName.class
od ClassName.class
hexdump ClassName.class
类加载器
-
不同的类加载器加载同一个类的字节码文件,所生成的两个
Class
对象是不同的,也就是说类加载器和类的字节码文件二者共同定义一个Class
对象。 - 类加载器种类:
- 启动加载器(Bootstrap ClassLoader):用于加载lib目录或
-XX:BootClassPath
下的rt.jar
包内的类 - 扩展加载器(Extention ClassLoader):加载ext目录下的类
- 应用加载器(Application ClassLoader):加载用户自定义的类路径(classpath)下的类,如果用户没有指定类加载器,则为默认的类加载器。
- 自定义加载器
- 启动加载器(Bootstrap ClassLoader):用于加载lib目录或
-
双亲委派模型(Parents Delegation Model):
类加载器在加载类时,首先会将加载的类传递给父类加载,如果父类的父类为
null
,则加载该类,否则就将类加载往上传递。当父类无法加载该类时,则抛出ClassNotFoundException
异常,则调用自身的findClass
方法去加载类,直到最低层。双亲委派模型中类加载器的父子关系采用组合方式,而不是采用继承方式实现。
双亲委派模型的代码实现如下:
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
Class<?> c = findLoadedClass(name);
synchronized(getClassLoadingLock(name)) {
try {
if(c == null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
}
if(c == null) {
c = findClass(name);
}
if(resolve) {
resolveClass(resolve);
}
return c;
}
}