『算法』面试常见问题jvm的调优思路( 二 )


Jvm调优一般都是对年轻代的调优 , 我们可以通过对代码评估 , gc回收频率 , 或通过可视化工具观察各个内存区域的变化来合理调整内存
比如
案例1:代码有问题 , 导致内存只增不减 。
解决方案:优化代码 。
时间复杂度:同一段代码执行的次数 , 或者所有代码执行的行数 。 重复次数越少、代码行数越少 , 时间复杂度越低 。
定义了太多的全局变量 , 导致不会被回收 。 Spring框架开发的项目中对象都是单例的 , 不会被轻易回收 。 注意:集合是绝对不要写成全局变量 。
递归:递归效率优于for循环 , 但是递归耗内存----等于以空间换时间 。 消耗内存特别大的代码不能采用递归 , 否则内存容易溢出 。
案例2:代码没有问题 , 但是GC回收特别频繁 。
解决方案:通过命令行或可视化工具查看内存实时占用情况及gc次数 , 合理分配各个区域的内存 , 如年轻代频繁发生gc则需要调整该区域大小 , 并且去分析是否有太大的变量频繁创建 , 如果有还需要进行代码优化
需要注意的是:

  1. 如果变量太大直接存储年老代 。
2.年老代空间不足会吞噬年轻代空间 。
避免年老代内存不足 , 但是年轻代内存过多 。 所以年老代借用年轻代的空间从而最大限度的保证内存不溢出 。 但是 , 如果年老代借用年轻代的话 , 会导致GC回收过滤频繁 , 而且还回收不了内存 。
因为压缩了年轻代空间 , 会导致年轻代的回收变得特别频繁(年轻代内存不够用了) 。
以上两点都会影响服务器的性能 。
如果变量是局部变量 , 并且即时释放引用 , 内存会得到即时回收 , 从而避免内存溢出 。 但是如果变量是全局变量 , 则引用不会因为线程结束而被GC回收 。 --------平时开发尽量不要写全局变量 。
而我们要如何去进行优化?可以通过设置以下参数
-XX:NewSize和-XX:MaxNewSize
设置年轻代的大小 , 建议设为整个堆大小的1/3或者1/4两个值设为一样大 。
-XX:SurvivorRatio
设置Eden和其中一个Survivor的比值 , 这个值也比较重要 。
-XX:+PrintTenuringDistribution
参数用于显示每次Minor GC时Survivor区中各个年龄段的对象的大小 。
-XX:InitialTenuringThreshol和-XX:MaxTenuringThreshold
【『算法』面试常见问题jvm的调优思路】设置晋升到老年代的对象年龄的最小值和最大值 , 每个对象在坚持过一次Minor GC之后 , 年龄就加1 。


推荐阅读