大厂面试
2021-12-01 13:55:28 10 举报
AI智能生成
jvm面试
作者其他创作
大纲/内容
对象何时进入老年代
15次GC被转移到老年代
动态年龄判断进入老年代
假如说当前放对象的Survivor区域里,一批对象的总大小大于了这块Survivor区域的内存大小的50%,
此时大于等于这批对象年龄的对象,就可以直接进入老年代了。
此时大于等于这批对象年龄的对象,就可以直接进入老年代了。
大对象直接进入老年代
“-XX:PretenureSizeThreshold”
Minor GC之后大于Survivor内存大小,直接进入老年代
垃圾回收触发时机
新生代
Eden区域满了
老年代
触发Full GC时机
当老年代的大小达到一定的比例之后,就会自动GC
Young GC之前,老年代内存空间大小<历代新生代进入老年代的平均对象大小
Minor gc之后的大小大于S区,且老年代空间不足
垃圾回收算法
新生代
复制算法
新生代内存分两部分,只使用其中一块内存
内存快满的时候,将存活的对象全部转入另一块内存,此时是内存连续的
标记 - 复制 - 清除
前提:对象存活率低
老年代
标记整理算法
比新生代速度慢10倍
若老年代频繁FULL GC,会严重影响系统性能
通过GC Roots判断对象是否有引用
GC Roots对象
虚拟机栈(帧栈中的局部变量表)中的引用对象
方法区中类静态属性引用的对象
方法区中常量引用的对象
本地方法栈中JNI (即一般说的 Native 方法) 的引用对
标记 - 清除 - 压缩
前提:对象存活率较高
垃圾回收器
Serial和Serial Old垃圾回收器
分别用来回收新生代和老年代的垃圾对象
单线程运行,其他线程卡死不动,已废弃
ParNew垃圾回收器
新生代垃圾回收器,支持多线程进行垃圾回收,采用复制算法
CMS垃圾回收器
老年代垃圾回收器,采用标记整理算法,会产生大量的内存碎片
基本原理
4阶段
初始标记
工作线程全部停止,进入stop the world,标记GC Roots直接引用的那些对象
并发标记
对老年代所有对象进行GC Roots追踪,其实是最耗时的
系统程序不会停止工作,此阶段不会对系统照成影响
重新标记
系统继续停下来进行标记
并发清理
重新恢复系统执行,清理掉之前标记为垃圾的对象
G1垃圾回收器
特点
统一回收新生代和老年代
最大特点:把Java堆内存拆分成多个大小相等的region,并且可以设置一个垃圾回收的预期停顿时间
region可能处于新生代,也可能处于老年代,实际上新生代和老年代的内存大小是动态变化的,由G1控制
还是有新生代,老年代、e区和s区之分的
清楚知道每个region的可以垃圾回收对象的大小,回收需要多长时间
G1提供专门region存放大对象,而不是直接让大对象进入老年代region,大对象既不属于新生代也不属于老年代
mixed垃圾回收的过程
初始标记,stop the world ,标记GC Roots直接引用的对象
并发标记
最终标记阶段,stop the world
混合回收
新生代GC如何优化
充足的堆内存
合理设置“-XX:MaxGCPauseMills”参数
mixed GC如何优化
老年代占堆内存45%的时候触发mixed垃圾回收,新生代+老年代+大对象一起回收
合理设置“-XX:MaxGCPauseMills”参数
核心参数配置
-Xms
Java堆内存的大小
-Xmx
Java堆内存的最大大小
-Xmn
Java堆内存中的新生代大小,扣除新生代剩下的就是老年代的内存大小了
-XX:PermSize
永久代大小
-XX:MaxPermSize
永久代最大大小
-Xss
每个线程的栈内存大小
jvm优化
思想
所谓JVM优化,就是尽可能让对象都在新生代里分配和回收,尽量别让太多对象频繁进入老年代,
避免频繁对老年代进行垃圾回收,同时给系统充足的内存大小,避免新生代频繁的进行垃圾回收。
避免频繁对老年代进行垃圾回收,同时给系统充足的内存大小,避免新生代频繁的进行垃圾回收。
新生代优化思路
每次minor gc之后,尽可能让对象都留在s区,不要进入老年代,因此要合理设置分配内存
避免动态年龄判断进入老年代,给S区足够空间
让该进入老年代的长期存活的对象早点进入老年代,不要一直呆在新生代里,把15次参数可以设置小一点
老年代优化思路
哪些对象会进入老年代
注解标注的业务逻辑组件长期存活进入老年代
大对象进入老年代
minor gc之后存活对象的大小>S区内存大小
动态年龄判断进入老年代
多久触发一次Full GC
类加载机制
准备
给类分配内存空间
类变量开辟内存空间,分配默认值
初始化
执行类的初始化代码
static静态代码块
初始化规则
何时初始化
new实例化对象,触发加载到初始化全过程
包含main方法的主类
初始化之前,父类必须先初始化
类的初始化阶段,仅仅是初始化类而已,跟对象无关,用new关键字才会构造一个对象出来
类加载器
BootStrap classloader:启动类加载器
Extension classloader:扩展类加载器
Application classloader
加载classpath指定路径下的类,理解为加载自己的Java代码
自定义加载器
双亲委派机制
委托自己的父类加载,最终传到顶层的启动类加载器
先让自己的父亲去找,找不到再自己找
避免类被重复加载
Tomcat打破了双亲委派机制,每个web应用都有一个webapp类加载器
内存区域划分
方法区(Metaspace)
存放类文件,运行常量池,静态变量
程序计数器
执行代码指令
每个线程都有一个单独的程序计数器,来记录代码执行的位置
虚拟机栈
每个线程都有自己的虚拟机栈
调用方法时,创建栈帧,入栈;方法执行完毕,出栈
用来存放方法内的局部变量
堆内存
存放对象,数组
0 条评论
下一页