OOM:
jvm里面有个oom(内存溢出),当时JVM发生内存溢出时,这个进程就停止了。
linux也有个oom(内存溢出):当系统检测出,内存不够用,会自动kill掉内存占用高的程序。所以说在实际生产环境当中,会监控服务器的内存状况,当内存占用达到阈值的时候,会发出告警。(或者说如果用到了K8s等容器化管理技术,系统会自动扩容)
nohup java -jar -server -Xms256M -Xmx256M -Xmn256M -XX:MaxMetaspaceSize=128M -XX:MetaspaceSize=128M -XX:+UseConcMarkSweepGC -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses -XX:+CMSClassUnloadingEnabled -XX:+ParallelRefProcEnabled -XX:+CMSScavengeBeforeRemark -XX:ErrorFile=/opt/app/message/jvm/hs_err_pid%p.log -Xloggc:/opt/app/message/jvm/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution -XX:+PrintClassHistogramBeforeFullGC -XX:+PrintClassHistogramAfterFullGC -XX:+PrintHeapAtGC -XX:HeapDumpPath=/opt/app/message/jvm -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:-OmitStackTraceInFastThrow > start.log 2>&1 &
设置虚拟机启动参数的目的:如果不限制jvm启动参数(不限制堆大小,不限制栈大小,他会默认是无限的,会不断的占用服务器的内存,直到服务器发生oom,影响到其他程序)
jvm里的内存溢出:
1,堆溢出:最常见的场景就是大list,list里面有很多元素。
堆溢出怎么解决:.
1,应该定位到导致内存溢出的对象
2,判断是否真的是内存溢出。先判断这个对象是不是正常的。如果不是,就得修复。如果是
1,要么去调优,通过优化逻辑来减少对象的大小
2,如果说硬件设施(操作系统)剩余内存还足够大,就可以将堆内存调大一些。
StringBuilder的append方法的intern。
1,如何判断对象已死?
算法1;引用计数法:在对象中添加一个引用计数器, 每当有一个地方 引用它时, 计数器值就加一; 当引用失效时, 计数器值就减一; 任何时刻计数器为零的对象就是不可 能再被使用的 ,但是不能解决循环引用的问题。
2,可达性算法分析
当这个对象,与GCROOT对象没有关联的时候,就认为这个对象已经死亡了
GCROOT包括四类:
两个栈两个方法区。
3,引用的四个等级
为什么说要有这个设置:为了满足当内存空间还足够时, 能保留在内存之中, 如果内存空 间在进行垃圾收集后仍然非常紧张, 那就可以抛弃这些对象 。
强:new Object(),只有当判断对象已经死的时候,才回收
软:在系统要发生oom,会回收所有的软引用对象,如果回收完,还是放不上这个对象,才溢出。,每次垃圾回收的时候,如果对象还没死,就不回收,但是在oom之前,不管有没有死,都会被回收。
弱:在每次垃圾回收的时候,不管有没有引用,都会被回收。
虚:相当于什么时候回收都没问题,也无法通过虚引用来取得一个对象实例。 为一个对象设置虚 引用关联的唯一目的只是为了能在这个对象被收集器回收时收到一个系统通知