JVM入门
1.请你谈谈jvm
2.什么是OOM,什么是栈溢出,怎么分析
3.jvm的常用调优参数有哪些
4.内存快照如何抓取,怎么分析Dumo文件
5.jvm中类加载器的理解
jvm的位置?
在运行操作系统之上,
jvm的体系结构
.java --> Class File----> 类装载器(class loader)--->运行时数据区Runtime(方法区(method),本地方法栈(native),堆(heap),栈(stack),程序计数 器)---->本地方法接口、本地方法库、执行引擎
栈、本地方法栈、程序计算器 这三个地方不会有垃圾的 栈用完就弹出去了
jvm调优就是在调整 堆和方法区,但是99%是堆
类加载器
加载class文件,getClass getClassLoader 只有一个类 对象有好几个
虚拟机自带的加载器,启动类(根)加载器(Bootstrap ClassLoader) 扩展类加载器(Extensions ClassLoader)
应用程序加载器(Application ClassLoader)
双亲委派机制:C:\Users\Legion\IdeaProjects\JavaSE\Basic\src\com\songyue\shuangqinTest
根加载器》扩展加载起》当前应用程序加载器
1.类加载器收到加载请求
2.将这个请求向上委托,一直到跟加载器
3.根加载器检查是否可以加载,能加载就结束,不能加载抛出异常通知子加载器
4.重复3
优点:
首先,保证了java核心库的安全性。如果你也写了一个java.lang.String类,那么JVM只会按照上面的顺序加载jdk自带的String类,而不是你写的String类。
其次,还能保证同一个类不会被加载多次。
沙箱安全机制
Native
带了native关键字的就说明java的作用范围达不到了,回去调用底层C语言的库,会进入本地方法栈、
JNI本地方法接口 java native interface 作用:扩展java类的使用,融合不同的语言为java所用,java诞生的时候C、C++横行,所以要有调用C、C++的程序
在内存区域中专门开辟了一块区域,本地方法栈,登记native方法,最终执行的时候,加载本地方法库的方法 通过JNI
PC寄存器
方法区
静态变量、常量、类信息(构造方法,定义接口)、运行时的常量池存放在方法区中,但是实例变量存放在堆内存中
栈:包括 8大基本类型+对象引用+实例的方法
是一种数据结构,程序=数据结构+算法
先进后出,后进先出:桶
队列:先进先出(FIFO first input first output)
为什么main先执行后结束,因为需要先把main压倒栈里面开始执行,然后调用其他方法,最后main结束,程序结束
栈内存,主管程序的运行,生命周期和线程同步,线程结束,栈内存也就释放了,对于栈来说不存在垃圾回收,一旦线程结束,程序也就结束了
栈+堆+方法区的交互关系
三种jvm
Sun公司HotSpot:咱们自己用的,另外的不重要
堆:gc垃圾回收主要在伊甸园和养老区,内存满了OOM,堆内存不够
Heap,一个jvm只有一个堆内存,堆内存大小是可以调节的
类加载器读取了类文件后,会把什么东西放到堆中: 类、方法、常量、变量、保存我们所有引用类型的真是对象
堆中还要细分为三个区域
Eden 新生区:伊甸园 里面有幸存0区,幸存1区 幸存区 分为from to 谁空谁是to
Old 养老区
Perm 永久区:JDK8以后叫元空间
新生区
一个类,诞生成长甚至死亡
伊甸园:所有的对象都是在这里new出来的
幸存区(0,1)
老年区
永久区:这个区域常驻内存,用来存放JDK自身携带的Class对象,interface元数据,存储的是java运行时的一些环境或者类信息,这个区域不存在垃圾回收
关闭VM虚拟机就会释放这个区域的内存
jdk1.6之前:永久代,常量池在方法区
jdk1.7: 永久代但是慢慢退化了,去永久代常量池在堆中
jdk1.8之后:无永久代,常量池在元空间 元空间逻辑上存在,物理上不存在
堆内存调优
oom时的解决办法:1.调整堆内存空间如果还有问题,就看代码有没有死循环垃圾代码
能够看到第几行代码出错 是最快的,内存快照分析工具Jprofiler
Jprofiler作用:分析Dump内存文件快速定位内存泄露,获得堆中的数据,获得大的对象
设置Dump:-Xms 设置初始化内存分配大小默认 1/644 , -Xmx设置最大分配内存默认 1/4 ,-XX:+PrintGCDetails GC清理的垃圾信息
-XX:+HeapDumpOnOutOfMemoryError 打印OOM
GC
轻GC针对新生代、幸存区
重GC(full)
jvm内存模型和分区~详细到每个区放什么
堆里面的分区有哪些 ,Eden from to 老年区说说他们的特点
GC的算法有哪些,标记清除法,标记压缩,复制算法,引用计数器怎么用的?
轻GC和重GC分别在什么时候发生?
复制算法就是把所有的东西在GC的时候都放在 幸存区中的某一个里面(比如Eden里面的和幸存区from里面的 ),所以没有内存的碎片,不过浪费空间
最佳使用条件是就是对幸存活度较低也就是新生区
标记清除算法:GC时标记,清除时清除没用的
缺点:两次扫描,浪费时间,会产生内存碎片
优点:不需要额外的空间
标记压缩:防止内存碎片
内存效率:复制算法》标记清除算法》标记压缩算法
内存整齐度:复制算法=标记压缩算法》标记清楚算法
内存利用率:标记压缩算法=标记清除算法》复制算法
没有最好的算法,只有最合适的 GC分代收集算法
年轻代:存活率低--》复制算法
老年代 :存活率高--》标价清除+标记压缩
每次GC都会将Eden中活的对象移到幸存区中,每次GC后Eden都是空的,当一个对象经历了15次GC都没有死,就会进入养老区
JMM:JAVA Memory Model(java内存模型)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通