JVM 调优总结

1、堆与栈java

一、堆是全部对象共享的,存储对象信息;算法

每个线程都有一个独立的线程栈,栈存储的是与当前线程相关的信息,包括局部变量、程序运行状态、方法返回值等。服务器


二、堆中存储的是对象,栈中存储的是基本类型堆中对象的引用多线程


三、栈的大小配置  -Xss并发


四、在运行栈中,基本类型和引用的处理是同样的,都是传值。spa


五、能够把一个对象看做为一棵树,对象的属性若是仍是对象,则仍是一棵树(非叶子节点),而基本类型则是叶子节点。操作系统


2、Java对象的大小线程

一、一个空的Object对象:对象

Object obj = new Object();递归

其所占的空间为: 8+4 =12 bytes 。其中8 bytes 是Java堆中对象的所需空间,4 bytes是栈中保存引用的所需空间


二、如下类

class NewObject

{

    int count;

    boolean flag;

    Object obj;

}

其的对象  NewObject  newObj = new NewObject();

newObj 所占空间 8 + 4 +1 + 4 = 17 bytes.

其中8 bytes 为 newObj 空对象大小,4 bytes为 int 大小,1 byte为 boolean 大小, 4 bytes为 obj引用大小。

又由于Java对象内存分配以8的整数倍来分,故而对象的大小为 24 bytes。


三、基本类型包装类的大小至少是16bytes。


3、强引用、软引用、弱引用

强引用:回收时候严格判断

软引用:内存紧张则回收,富余则不回收

弱引用:每次GC一定回收,生命周期只存在于一个垃圾回收周期。


4、GC 基本策略


一、引用计算:没法处理循环引用


二、标记-清除:从root节点开始标记全部引用对象,遍历堆,清除未标记对象。缺点是须要暂停整个应用,产生内存碎片。


三、复制:将内存分为两块,每次只使用其中一块。回收时候复制到另外一块。


四、标记整理:结合 “标记-清除”  和 “复制”, 不过不是复制到另外一块内存,而是将对象放紧凑。


5、GC 分区策略


一、增量收集:实时垃圾回收。


二、分代收集:把对象分为年轻代、年老代、持久代,对于不一样生命周期对象采用不一样算法。


6、GC 线程策略


一、串行收集:单线程处理,没法使用多处理器的优点。须要暂停整个运行环境。

优势:简单,效率高。

缺点:只适合小型应用,数据量比较小。

配置:-XX:+UseSerialGC


二、并行收集:多线程处理,速度快,效率高。须要暂停整个运行环境。

优势:吞吐量大,适用于数值计算、后台处理。

缺点:响应时间长。

配置:XX:+UseParallelGC   -XX:+UseParallelOldGC    -XX:ParallelGCThreads=<N>   -XX:MaxGCPauseMillis=<N>   -XX:GCTimeRatio=<N>


三、并发收集:GC的同时不须要暂停整个运行环境。

优势:响应时间快,适用于Web服务器等。

缺点:吞吐量没那么大。

配置:-XX:+UseConcMarkSweepGC  -XX:CMSInitiatingOccupancyFraction=<N>


7、分代回收


一、年轻代(Yong):一个Eden区,两个Survivor区。Eden满,放入一个Survivor。Survivor放入另外一个Survivor。另外一个Survivor满,放入年老代。


二、年老代(Tenured):年轻代经历N次GC后,对象放到年老区。放的是生命周期较长的数据。


三、持久代(Permanent):Java 类的 Class 信息,与GC关系不大。


Minor GC:只要Eden满即触发,速度很快。

Full GC:整个堆回收,速度慢。在年老代或者持久代满的时候调用。


8、典型配置

java -Xmx3550m -Xms3550m -Xmn2g –Xss128k  -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0 XX:+UseConcMarkSweepGC -XX:+UseParNewGC  

-Xmx3550m: 最大可用内存

-Xms3550m:初始内存。此值能够设置与-Xmx相同,以免每次垃圾回收完成后JVM从新分配内存。

-Xmn2g:年轻代大小

-Xss128k:每一个线程的栈大小

-XX:NewRatio=4: 年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)

-XX:SurvivorRatio=4:年轻代中Eden区与Survivor区的大小比值

-XX:MaxPermSize=16m: 持久代大小 

-XX:MaxTenuringThreshold=0: 垃圾最大年龄。若是设置为0的话,则年轻代对象不通过Survivor区,直接进入年老代

-XX:+UseParallelGC:选择并行收集器

-XX:ParallelGCThreads=20: 并行收集器的线程数

-XX:+UseParallelOldGC: 年老代垃圾收集方式为并行收集

-XX:MaxGCPauseMillis=100:每次年轻代垃圾回收的最长时间

-XX:+UseAdaptiveSizePolicy:自动选择年轻代区大小和相应的Survivor区比例

-XX:+UseConcMarkSweepGC:设置年老代为并发收集

-XX:+UseParNewGC: 设置年轻代为并行收集

-XX:CMSFullGCsBeforeCompaction=5:运行多少次GC之后对内存空间进行压缩、整理。

-XX:+UseCMSCompactAtFullCollection:打开对年老代的压缩


9、调优总结


一、吞吐量优先:

年轻代大并行垃圾收集、年老代小

尽量回收掉大部分短时间对象,减小中期的对象,而年老代尽存放长期存活对象。


二、响应时间优先:

年轻代大、并发垃圾回收、年老代适中。

年老代使用并发收集器,因此其大小须要当心设置,通常要考虑并发会话率和会话持续时间等一些参数。若是堆设置小了,能够会形成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;若是堆大了,则须要较长的收集时间


10、年老代碎片问题:

解决:

一、-XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩。

二、-XX:CMSFullGCsBeforeCompaction=0:上面配置开启的状况下,这里设置多少次Full GC后,对年老代进行压缩


11、常见JVM 异常

一、java.lang.OutOfMemoryError: Java heap space

缘由:典型的内存泄露,全部堆空间都被没法回收的垃圾对象占满。

解决:找到泄露点,通常是集合对象引用。


二、java.lang.OutOfMemoryError: PermGen space

缘由:持久代占满,没法为新的class分配存储空间而引起的异常。主要缘由是大量动态反射生成的类不断被加载。不一样的classloader 即使使用了相同的类,可是都会对其进行加载,至关于有一个class会被N个classloader加载N次。

解决:-XX:MaxPermSize=16m


三、java.lang.StackOverflowError

缘由:递归没有返回,或者循环调用。

解决:修正代码


四、Fatal: Stack size too small

缘由:线程空间大小被限制

解决:增大线程栈,-Xss2m。也多是代码内存泄露。


五、java.lang.OutOfMemoryError: unable to create new native thread

缘由:操做系统没有足够资源产生这个线程

解决:配置系统,如ulimit。减少线程栈大小,-Xss。

相关文章
相关标签/搜索