1、关于对象结合JVM
写功能代码时,尽量在一个方法里少创建对象,因为并发量高的时候,频繁的创建和销毁大量对象,会对 JVM 产生巨大压力,可能会崩溃。
2、关于 JVM 参数设置
在实际开发中,可以工具测试一个对象占多少内存,计算下并发量假如1000的时候,对象一共会占用多少内存。再结合新生代、老年代的垃圾清除思想,来设置新
生代中三区、老年代的内存大小。
3、关于对象
在实际业务代码里,一般加了@Service @Controllere 的对象,都是创建一次,一直使用,所以会在创建后,经过 MinorGC 进入到老年代。
我们在接口,方法里面的局部变量,都是使用一次后基本就不再使用(除非方法逃逸),所以对象在新生代里,很快就会回收,不会进入老年代。
我们实际写业务代码,就尽量考虑到创建对象的时候,不要在一个方法里大量创建对象,避免频繁出发 MinorGC。(结合第一条心得)
4、关于常量类和数据字典
如果只是单纯的 key ,就可以用常量类 - 静态变量来定义;
如果是不可变 key + value 格式,可以用枚举来定义;
如果是不可变的 key 和可变的 value,那可变的 value 就从持久化的地方获取,例如 mysql。 key 的话就可以用常量类 - 静态变量来定义。
5、关于如何分析 JVM 优化
分析一个项目,1秒钟会产生多少对象,新声代的 Eden 区 和 Survivor 区有多大。多少秒后会发生一次 YGC。发生 YGC 时,如果有空间担保规则,老年代的剩余大小是否大于新生代每次回收存活对象平均内存大小。如果老年代放的下,则发生 YGC,如果老年代放不下,则发生 FullGC。
如果新生代的 Eden 区回收垃圾,存活的对象大于 Survivor 区的大小,则这些存活对象会直接存到老年代中,会使老年代迅速的存满对象。
所以优化,就是先分析上述情况。然后针对性的,调大堆大小以及 Survivor 区的大小,使对象从 Eden 区存活,会复制到 Survivor 区。
并且如果是大内存的机器,面向外网网友访问的,应该将垃圾回收器设置为 G1 垃圾回收器。
防止频繁 FullGC:禁止动态年龄判断,以及确保每次 MinorGC 后存活的对象,能放在 Survivor,不会直接移动到老年代。(让进入老年代的对象尽量少)