Java HotSpot™ 64-Bit Server VM (build 25.181-b13, mixed mode)
- JRockit
Oracle JRockit (原来的 Bea JRockit)电脑软件,系列产品是一个全面的Java运行时解决方案组合
- J9
J9 是一个IBM推出的Java虚拟机和类库,J9在IBM的从移动设备到企业解决方案中广泛的被使用
==============================================================
heap,一个jvm只有一个堆内存。堆内存的大小可以调节的。
类加载器读取了类文件后,一般会把什么放到堆中呢?类,方法,常量,变量,保存所有引用类型的真实对象。
堆内存中还要细分三个区域:
-
新生区(伊甸园区)young/new
-
养老区 old
-
永久区 perm
其中,好多次没被垃圾回收GC-garbage collect掉,就进入幸存0,1;过一段时间,还没被回收掉就进入养老区。垃圾回收有轻量级的GC,还有当养老区都快满的时候,重量级的GC。
GC垃圾回收主要在伊甸园区和养老区。
内存满了即OOM,out of memory堆内存不够,说明程序严重,堆都爆了。
JDK8以后,永久存储区就叫“元空间”了
================================================================
类:诞生和成长的地方,甚至死亡。
分为伊甸园区和幸存者区(0区和1区),所有的对象都是在伊甸园区new出来的。
假设伊甸园区大小是10个,等到伊甸园区满的时候,会触发轻量GC,删除了9个,幸存了1个进入幸存者0区。那么此时伊甸园区又有10个空位置了。
这里注意幸存者0区和幸存者1区是来回交换的,不是不变的。
等到幸存者0,1区都满了,触发重GC,留下来的存到养老区。
真理:经过研究,**99%**对象都在伊甸园区就结束了,很少看到OOM报错。(可以新建一个字符串,一直往上加字符,加到爆OOM)
================================================================
这个区域是常驻内存的。用来存放JDK自身携带的Class对象。Interface元数据,存储的是Java运行时的一些环境或类信息。这个区域不存在垃圾回收!关闭JVM虚拟机就会释放这个区域的内存
如果一个启动类,加载了大量的第三方jar包
例如:Tomcat部署了太多的应用,大量动态生成的反射类,不断的被加载。直到内存满,就会出现OOM(Out of Memory)
方法区是共享的。伊甸园区的各个对象调用方法区的方法。
上面这个图是存在于堆区的。而元空间和方法区其实不是存在于堆中的,所以又叫非堆。
实测
默认情况下,最大将近2G,电脑8G,差不多1/4。而初始化内存123M,差不多是8G的1/64。
设置虚拟机的内存大小
-Xms1024m -Xmx1024m -XX:+PrintGCDetails
-
-Xms1024m:初始化内存
-
-Xmx1024m:最大内存
-
-XX:+PrintGCDetails:打印结果
OOM演示
GC一直在清理内存,后来又有了重GC,再轻GC,再重GC。
==================================================================
- OOM
Out Of Memory
堆内存满了
**措施:**尝试扩大堆内存看结果;分析内存,看哪里出了问题,就是上面的print,或者用下面专用的插件
-
一个项目中,具体如何排除OOM故障
-
能够看到代码第几行出错:内存快照分析工具:MAT,JProfiler
-
debug,一行行分析,不太现实。
-
MAT 和 JProfiler 的作用
-
分析dump内存文件,快速定位内存泄漏
Dump文件是进程的内存镜像。可以把程序的执行状态通过调试器保存到dump文件中。Dump文件是用来给驱动程序编写人员调试驱动程序用的,这种文件必须用专用工具软件打开
-
获得堆中的数据
-
获得大的对象
-
JProfiler
-
安装IDEA插件
- 安装客户端
- 测试OOM
代码
public class Demo03 {
/**
- 1m数组
*/
byte[] bytes = new byte[1024*1024];
public static void main(String[] args) {
ArrayList list = new ArrayList<>();
int count = 0;
try{
while(true){
list.add(new Demo03());
count++;
}
}catch (Error e){
System.out.println(count);
e.printStackTrace();
}
}
}
配置VM参数
-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError
-
-Xms1m:初始化内存为1m
-
-Xmx8m:最大内存为8m
-
-XX:+HeapDumpOnOutOfMemoryError:当出现OOM时,输出Dump文件
想要知道其他错误,只需要改成其他错误名,写进配置中的VMoption就可以生成dump文件dump内存,定位错误了。
格式:HeapDumpOnXXX错误
栈里面是没有垃圾的,只有堆里面有
分析
=====================================================================
GC的作用区只有方法区和堆。分类有 轻GC 和 重GC,轻GC主要是 新生代,重GC是 全局的清理
幸存区一个from,一个to。两个 相互转换。
即幸存区0可以是from,也可以是to,幸存区1可以是from,也可以是to。
每个对象有被用的次数的统计,当次数为0时,就清除出去了。但是计数器本身也有消耗,并且碰到有些死循环,就会一直计数出不来。现在一般不采用此方法。
空的始终都是to。当幸存0和幸存1区都有一个的话,就把其中一个复制到另一个,这样,有两个对象的就是from,空的就为to。要是把from中的两个复制到to中,那么to就变成了from,from就变成了to。
每次垃圾清理完之后,伊甸园区空,to区空了。其中的对象等到 15次 后,进入到养老区。
-
优点:没有内存的碎片
-
缺点:浪费一个幸存区空间,多了一半空间永远是空to。假设对象100%存活,复制成本很高。
-
最佳使用场景:对象存活度较低的时候,即在新生区中用复制算法。
清除
回收垃圾时,扫描这些对象,对活着的对象进行标记。清除的时候,对没标记的清除掉。
-
优点:不需要额外的空间
-
缺点:两次扫描,严重浪费时间,会产生内存碎片(对象存储的时候用hash,找内存也需要时间成本,对象位置很散乱)
压缩
-
内存效率:复制算法 > 标记清除算法 > 标记压缩算法 (时间复杂度 )
-
内存整齐度:复制算法 = 标记压缩算法 > 标记清除算法
-
内存利用率:标记压缩算法 = 标记清除算法 > 复制算法
最优算法
-
最优算法:没有最好,只有最合适的算法。GC:不同位置用不同的垃圾收集算法
-
年轻代,年轻区:存活率低,使用复制算法
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
最后
学习视频:
大厂面试真题:
64737)]
[外链图片转存中…(img-GPstxMY5-1711923664737)]
[外链图片转存中…(img-nbpUNIz4-1711923664738)]
[外链图片转存中…(img-Q2WDNl4a-1711923664738)]
[外链图片转存中…(img-QOjCCo4r-1711923664739)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-VELafq5n-1711923664740)]
最后
学习视频:
[外链图片转存中…(img-RXXmb18I-1711923664740)]
大厂面试真题:
[外链图片转存中…(img-WX1hCoFs-1711923664741)]