- 受限于实际生产环境未必能够查出问题(jira:一个测试平台的问题)
- 案例
- 每一个lambda表达式对象都会在内存中产生一个新的class,class分配在方法区!太多的话方法区会OOM
- 直接内存溢出(少见)
- 栈溢出问题
- 下面哪种写法更好
- System.gc显式调用会立即执行吗
- new大量线程的时候,可能会产生Unable to create new native thread的问题(异常?)
- 实际环境中确实有一些服务器是通过不断重启来优化的,比如游戏服务器(维护中,20分钟后重试)、12306每天晚上11点到8点是不允许买票的、地下城与勇士之前也这样
- 出现卡顿或者其他的什么问题,可以通过更换垃圾回收器来试一试!
- 跟面试官聊天不要很死板,要真实、精妙、灵活,有什么说什么,要变通,什么都可以说,更现实真实性,显示出经验上的丰富性!!!—->没把握的时候可以跟同学、老师交流交流,问问别人这样说合不合适(当局者迷,旁观者清)
- 🌟重启和扩内存是解决问题的两大法宝!!!
- 提交了Pool Request(PR)—->bug?
- 项目驱动
- CPU飙高—->频繁GC,GC的时候需要使用CPU资源(为什么GC?因为频繁产生新对象)
- 至此,有了JVM调优的经验!
受限于实际生产环境未必能够查出问题(jira:一个测试平台的问题)
- 知道有那么一个bug,但是没什么大问题,就允许那个bug存在了两年
- 频繁GC,能运行就是慢一点,等到非常慢的时候就reboot一下
- 解决方案:扩内存了,触发GC的时间就往后延期了
- 15h会有FGC,现在变成24h会FGC
- 到了24h重启一下就行了
- 每24h重启一次
- 50g内存,G1可能会好很多!!!
- 也可以换垃圾回收器—->换了之后一个月没有卡顿了
- 扩内存!!!并且将垃圾回收器换成G1!!!
- 硬件和软件两个角度
- G1用的是jdk8,8的时候其实就比较完善了,jdk9默认垃圾回收器就是G1了
- jdk11还是jdk13就把CMS去掉了,CMS没用了,已经完成历史使命了
- CMS在任意版本里面都不是默认的垃圾回收器
- 最后还不知道是哪的问题,但问题还是解决了;有可能就是内存不够大而导致的不断GC
- 真实的调优:扩内存 + 换G1
案例
- 笛卡尔乘积—->1000*1000,百万级别的报表
每一个lambda表达式对象都会在内存中产生一个新的class,class分配在方法区!太多的话方法区会OOM
- 方法区会一直往里面装,因为方法没有结束所以他就不会被回收
- 方法区的清理每个垃圾回收器不一样:
- 有的根本就不清理
- 有的会清理但是条件非常苛刻
- 对于方法区溢出尽量少和面试官聊,知道有这么回事就行了(这件事很少发生,自己装在心里就行)
- 动态代理不断产生class,但是没有被回收是可能造成方法区的OOM的
- 牛逼的话可以说lambda在循环中造成OOM
-
直接内存溢出(少见)
《深入理解java虚拟机》P59,使用Unsafe分配直接内存,或者使用NIO的问题
栈溢出问题
-Xss
设定太小- 不要和面试官说,自己心里清除就行
- 栈溢出只能把栈调大,没有什么特殊的办法
下面哪种写法更好
- 第一种写法更好,但是实际中可能更多的是第二种
- 第一种栈中就一个o引用,每一个new都会指向新的对象,之前的对象可以被回收
- 第二种每一次循环都会产生一个新的对象以及引用,这样就造成了在栈中有好多引用,并且堆中的对象不可以被回收,就容易OOM
- 第二种循环结束就会释放了,不结束还是在那里的
- 还涉及到jvm回收的优化,对这种循环回收的优化,有的Hotspot版本在里面优化就不会进行回收
System.gc显式调用会立即执行吗
- 有参数设置,可以禁用这个GC
-XX:DisableExplictGC
- 默认不是打开的,打开之后
System.gc
显式调用会被禁用(不管用) - 生产环境中一般将这个参数
-XX:DisableExplictGC
打开!!! - 打开那个参数来禁用
System.gc
的显式(精确)调用,以防止System.gc
进行GC的时机不确定而造成的问题 - 除非自己做实验,否则不要在程序中使用
System.gc
,他不会立即调用,但是在程序中说不定什么时候就会调用 - 回调但是不会立即调用,假如在循环里不小心写了
System.gc
有可能就会产生频繁的GC(FGC)
new大量线程的时候,可能会产生Unable to create new native thread的问题(异常?)
- 现在一般用大量线程干事的话,就用线程池
- new大量线程会产生native thread OOM,(low,应该用线程池)
- 在循环中不断new thread有点过分,这里的OOM是OS中的线程满了不能在创建了,而不是jvm的堆内存满了,此时堆内存还是有可能没有满的
- 解决方案:减少堆空间???
- jvm内存一般不会把整体内存都占空了,一般占个70%-80%就不错了
- 预留更多内存来产生native thread
- JVM内存占物理内存比例50%-80%,留20%给native thread绝对足够了,肯定是没问题的,除非jvm把物理内存全占了
- native thread的内存不是分配在jvm中的,而是在jvm内存以外的内核空间中???
- 本地内存不够用了,产生本地内存的溢出
- 自己new线程本身就不对,应该用线程池