Java的性能优化,整理出一篇文章,供以后温故知新。
在学习Java GC 之前,我们需要记住一个单词:stop-the-world 。它会在任何一种GC算法中发生。stop-the-world 意味着JVM因为需要执行GC而停止了应用程序的执行。当stop-the-world 发生时,除GC所需的线程外,所有的线程都进入等待状态,直到GC任务完成。GC优化很多时候就是减少stop-the-world 的发生。
需要注意的是,JVM GC只回收堆区和方法区内的对象。而栈区的数据,在超出作用域后会被JVM自动释放掉,所以其不在JVM GC的管理范围内。
-
对象没有引用
-
作用域发生未捕获异常
-
程序在作用域正常执行完毕
-
程序执行了System.exit()
-
程序发生意外终止(被杀线程等)
在Java程序中不能显式的分配和注销缓存,因为这些事情JVM都帮我们做了,那就是GC。
有些时候我们可以将相关的对象设置成null 来试图显示的清除缓存,但是并不是设置为null 就会一定被标记为可回收,有可能会发生逃逸。
将对象设置成null 至少没有什么坏处,但是使用
System.gc() 便不可取了,使用
System.gc() 时候并不是马上执行GC操作,而是会等待一段时间,甚至不执行,而且
System.gc() 如果被执行,会触发
Full GC ,这非常影响性能。
eden区空间不够存放新对象的时候,执行
Minro GC。升到老年代的对象大于老年代剩余空间的时候执行
Full GC,或者小于的时候被HandlePromotionFailure 参数强制
Full GC 。调优主要是减少
Full GC的触发次数,可以通过 NewRatio 控制新生代转老年代的比例,通过MaxTenuringThreshold 设置对象进入老年代的年龄阀值(后面会介绍到)。
新生代(Young generation):绝大多数最新被创建的对象都会被分配到这里,由于大部分在创建后很快变得不可达,很多对象被创建在新生代,然后“消失”。对象从这个区域“消失”的过程我们称之为:
Minro GC 。
老年代(Old generation):对象没有变得不可达,并且从新生代周期中存活了下来,会被拷贝到这里。其区域分配的空间要比新生代多。也正由于其相对大的空间,发生在老年代的GC次数要比新生代少得多。对象从老年代中消失的过程,称之为:
Minro GC 或者
Full GC。
**持久代(Permanent generation)**也称之为 方法区(Method area):用于保存类常量以及字符串常量。注意,这个区域不是用于存储那些从老年代存活下来的对象,这个区域也可能发生GC。发生在这个区域的GC事件也被算为 Major GC 。只不过在这个区域发生GC的条件非常严苛,必须符合以下三种条件才会被回收: