Java基础八股复习3 jvm-垃圾回收与栈溢出

发布于:2025-08-20 ⋅ 阅读:(15) ⋅ 点赞:(0)
  1. StackOverFlow栈溢出:
    jvm虚拟机栈中占用栈内存较大的是局部变量表,也就是说如果方法中大量定义局部变量,或者出现循环嵌套调用方法时,每个方法都会创建一个栈帧,这种情况可能将栈内存打满
    需要注意不要在方法中定义大量局部变量,这种情况一般不会,一般都会使用对象来处理,对象在堆中,对栈内存无影响。还有就是代码开发中尽量避免出现循环嵌套的情况,或者出现死循环的情况。

  2. OOM(outOfMemory)堆内存溢出:

1)垃圾回收:
我们现在用的jdk17使用的是G1垃圾回收器

  • Full GC 全量垃圾回收

Jvm对整个堆内存进行垃圾回收,会清理所有线程,回收所有可回收的对象,system.gc()可手动调用
触发条件:老年代空间不足或者元空间耗尽

  • Young GC
    清理eden和suvivor区内存,清理短期对象内存,eden区不足时触发,将存活的对象复制到suvivor区,将eden区清空

年轻代:

  • 新对象先在eden区,多次youngGc后仍存活进入suvivor区,最终晋升到老年代

老年代
多次 younggc存活的长期对象
eden和suvivor区溢出的对象,jvm会将其放入老年代

对象占用内存过大,超过基础配置,也会进入老年代

进入之前会先判断,老年代内存满不满足需要,不满足会先进行一次oldgc或者full gc,再放入

优化full gc : 根据应用内存使用情况和性能目标,调整jvm参数,比如堆大小、新生代大小、垃圾回收器参数等

总结:
对象垃圾回收全过程:
对象创建后放在eden区,经过至少一次youngGc后进入suvivor区,再经过多次或者suvivor区空间不足后进入老年代,老年代空间不足触发fullGc,频繁fullGc可能导致系统卡顿
G1垃圾回收:
标记整理法,将堆内存划分为多个区域(2048),标记最需要进行垃圾回收的区域执行,将多个eden区的对象复制存放在新区域,这个区域称为suvivor区,再将原来的几个eden区对象清空
优点:划分为多个区域,只回收最高价值的部分区域,垃圾回收更高效,不容易出现卡顿

2)jvm优化
1-垃圾回收老年代的执行时间很久,尽量减少老年代的执行频率
2-如果堆内存过小,容易引发oom,触发fullGc,需要合理设置堆内存,尤其是新生代内存如果过小,就会频繁触发老年代垃圾回收,造成系统卡顿
3-代码层面控制使用对象的大小和避免循环创建对象

export JAVA_OPTS=" -Xms4096m -Xmx4096m -XX:MaxMetaspaceSize=512m -XX:MetaspaceSize=512m -XX:MaxDirectMemorySize=2456m -XX:ConcGCThreads=0 -XX:ParallelGCThreads=4 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/export/Logs -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/export/Logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=10M -XX:CICompilerCount=2 -Djava.library.path=/usr/local/lib -server -XX:HeapDumpPath=/export/Logs -Djava.awt.headless=true -Dsun.net.client.defaultConnectTimeout=60000 -Dsun.net.client.defaultReadTimeout=60000 -Djmagick.systemclassloader=no -Dnetworkaddress.cache.ttl=300 -Dsun.net.inetaddr.ttl=300 "

-Xms4096m 设置初始堆内存,-Xmx4096m 设置最大堆内存
-xmn 设置新生代内存大小
XX:+UseAdaptiveSizePolicy 动态内存策略,在youngGc时动态调整suvivor区大小,可以让新生代挪用部分老年代内存,减少对象进入老年代的机会


网站公告

今日签到

点亮在社区的每一天
去签到