• JVm调优总结


    1 jvm虚拟机中有数据类型分为两种,基本类型和引用类型,基本类型包括byte,short,int,long,float,double,boolean,char;引用类型包括类类型,接口类型,和数组

    2堆和栈是程序运行的关键,栈是运行时的单位,解决运行是的问题,堆是存储的单位,解决存储的问题。

    3一个线程需要一个独立的线程栈,而所有的线程共享堆中的数据。

    1堆和栈的分离,使得堆中的数据可以被多个线程共享,一方面提供了有效的数据交互方式,另一方面,堆中的共享的常量和缓存可以被所有栈访问,节省了空间。

    2栈因为运行需要,比如保存系统运行的上下文,需要进行地址划分,只能向上增长,限制栈存储内容的能力。而堆中的内容可以根据需要动态增长。

    1在java中main就是栈的起点,也是程序的起始点。

    2堆中存放的是对象。栈中存放的是基本数据类型和对象的引用。对象的大小不可估计。而基本数据和对象的引用对应的大小是固定的的,占用的空间小。

    3程序运行永远在栈中进行,传递参数是只存在传递基本数据和对象的引用的副本,而不是传递对象本身。在栈中,基本类型和引用的处理是一样的,都是传值。

    下面是一个很好的列子,别的地方找的。

    1. class  Test
    2. {
    3.   public  static  void  main(String  args[])
    4.   {
    5.     int  val;
    6.     StringBuffer  sb1, sb2;
    7.  
    8.     val = 10;
    9.     sb1 = new  StringBuffer ("apples" );
    10.     sb2 = new  StringBuffer ("pears" );
    11.     System .out.println("val is "  + val);
    12.     System .out.println("sb1 is "  + sb1);
    13.     System .out.println("sb2 is "  + sb2);
    14.     System .out.println("" );
    15.  
    16.     System .out.println("calling modify" );
    17.     // 按值传递所有参数
    18.     modify(val, sb1, sb2);
    19.     System .out.println("returned from modify" );
    20.     System .out.println("" );
    21.  
    22.     System .out.println("val is "  + val);
    23.     System .out.println("sb1 is "  + sb1);
    24.     System .out.println("sb2 is "  + sb2);
    25.   }
    26.  
    27.   public  static  void  modify(int  a, StringBuffer  r1,
    28.                             StringBuffer  r2)
    29.   {
    30.       System .out.println("in modify..." );
    31.       a = 0;
    32.       r1 = null ;  //1
    33.       r2.append(" taste good" );
    34.       System .out.println("a is "  + a);
    35.       System .out.println("r1 is "  + r1);
    36.       System .out.println("r2 is "  + r2);
    37.   }
    38. }
    39.  
    Java  应用程序的输出
    1.  
    2. val is 10
    3. sb1 is apples
    4. sb2 is pears
    5.  
    6. calling modify
    7. in modify...
    8. a is 0
    9. r1 is null
    10. r2 is pears taste good
    11. returned from modify
    12.  
    13. val is 10
    14. sb1 is apples
    15. sb2 is pears taste good
    16.  


    这段代码声明了三个变量:一个整型变量和两个对象引用。设置了每个变量的初始值并将它们打印出来。然后将所有三个变量作为参数传递给  modify  方法。 

    modify  方法更改了所有三个参数的值:  

    将第一个参数(整数)设置为  0 。  
    将第一个对象引用  r1  设置为  null 。  
    保留第二个引用  r2  的值,但通过调用  append  方法更改它所引用的对象(这与前面的  C++  示例中对指针  p  的处理类似)。 

    当执行返回到  main  时,再次打印出这三个参数的值。正如预期的那样,整型的  val  没有改变。对象引用  sb1  也没有改变。如果  sb1  是按引用传递的,正如许多人声称的那样,它将为  null 。但是,因为  Java  编程语言按值传递所有参数,所以是将  sb1  的引用的一个副本传递给了  modify  方法。当  modify  方法在  //1  位置将  r1  设置为  null  时,它只是对 sb1  的引用的一个副本进行了该操作,而不是像  C++  中那样对原始值进行操作。 

    另外请注意,第二个对象引用  sb2  打印出的是在  modify  方法中设置的新字符串。即使  modify  中的变量  r2  只是引用 sb2  的一个副本,但它们指向同一个对象。因此,对复制的引用所调用的方法更改的是同一个对象。
     
    java对象的大小
    一个空Object的大小为8字节。
    引用类型
    强引用,软引用,弱引用
    强引用 我们在生成对象是Java虚拟机生成的引用,强引用环境下不会被垃圾回收,而软引用和弱引用一般做为缓存来使用。弱引用一定会被垃圾回收。软引用在内存紧张的时候会被垃圾回收。我们一般都是用的强引用。
     
    基本垃圾回收算法
    引用技术:此对象有一个引用,增加一个计数,减少一个就计数减一,垃圾回收时,收集计数为0的对象。致命的无法处理循环引用问题。
    标记-清除:从引用节点开始标记所有被引用的对象,遍历整个堆,清除没有引用的对象。
    复制:把内存划分为两个部分,垃圾回收时,遍历使用的部分,把正在使用的对象复制到另一个区域,清空原来的区域。算法缺点,要使用两倍的内存空间。
    标记-复制:结合复制和清楚的优点,标记正在使用的对象,把正在使用的对象压缩到堆的其中一块。
     
    按分区对待的方式划分
    增量收集:在应用进行的时候同时回收垃圾。
    对象建立和对象回收问题
    1 垃圾回收前,暂停对象建立。清理完成之后再运行,应用太大的时候暂停时间太长。
    2 并发垃圾回收:回收和建立同时进行,对性能要求提高,而且碎片不好整理。
     
    分代收集:把对象分为年轻代,年老代,持久代,不同生命周期采用不同的垃圾回收算法。现在的垃圾回收器都是按照此算法。
    把不同的对象放在不同的代上,分别对待,采取不同的回收算法,提高效率。
    新生成的对象都放在年轻代,年轻代分为三个区,存活时间很久的会进入老年代,老年代中存活的都是生命周期很长的,持久代中存放的静态文件如java类,方法。
     
    java回收的起点是一些根对象(java栈,静态变量,寄存器。。)对 应  标 记-清除。从起点遍历,找到正在使用的对象,没有使用的就回收。
    复制,和标记-整理方式都可以清理碎片。
     
    垃圾回收分两种类型 一种scavenge gc主要处理年轻代,把第一个去中没存活的对象回收,在把存活的放在第二个区,
    还有一种对整个堆进行清理,在年老代被写满,持久代写满用到full gc,full gc很慢,少用。
     
    按照系统线程分
    串行收集:单处理器机器,也可以用在小数据量(100m)情况的多处理器机器。可以使用-XX:+UseSerialGC打开。
    并行收集:使用多线程垃圾回收工作,速度快,效率高。对老年代还是默认单线程,可以使用-XX+UserParallelGC打开,使用-XX:+UseParallelOldGC打开老年代多线程。使用-XX:ParallelGCThreads=<n>设置并行的线程数,N可以和机器处理器数量相等。最大垃圾回收暂停,-XX:MaxGCPauseMillis=<N>,N为毫秒,指定这个值会减少应用的吞吐量。   吞吐量是垃圾回收时间和非垃圾回收时间的对比,通过-XX:GCTimeRatio=<N>设定,公式为1/(1+n),如n=19,则为5%,默认为1%。适合多CPU,对应用响应时间无要求的中,大型应用。
    并发收集:前面两个在垃圾回收是会暂停整个运行环境,适合对响应要求比较高的中,大规模应用。使用-XX:UseConcMarkSweepGC打开。对处理器要求很高。
     
    以下配置主要针对分代垃圾回收算法
    JVM中堆的大小设置有三个限制,相关操作系统的数据模型(32位64位),系统可用虚拟内存限制,机器物理内存限制,32位系统一般1.5到2G
    典型设置
    -Xmx3550m:设置JVM最大可用内存3550M,
    -Xms3550m:JVM初始内存为3550m,可以与和第一个相同,避免垃圾回收完成之后JVM重新分配内存。
    -Xmn2g:设置年轻代大小2G;整个堆大小=年轻代+年老代+持久代大小,持久代一般固定为64m,增大年轻代,将影响年老代的大小,对系统性能影响很大,Sun公司推荐为整个堆的3/8;
    -Xss128K;设置每个线程的栈的大小,减少这个值能生成更多的线程,但操作系统对线程的个数有限制的,一般为3000-5000;
     
    并行收集器适合对吞吐量优先的系统,
    并行收集器适合对响应时间优先的系统,并发收集器不会对内存空间进行压缩整理。
     
    辅助打印信息,以供调试
    -XX:+PrintGC;-XX:+PrintGCDetails;-XX:+PrintGCTimeStamps可以和前两个混合使用。
     
     
    常见配置
    堆配置
    -Xms:初始堆大小
    -Xmx:最大堆大小
    -XX:NewSize=N:设置年轻代大小
    -XX:NewRatio=N设置年轻代和老年代的比例  比如n=3;表示年轻代和老年代 1:3
    -XX:SurvivorRatio=n  年轻代中Eden区和Survivor区的比值,Survivor有两个区,n=3,表示一个Survivor区和Eden区比是1:3,整两个Survivor区和Eden区为2:3
    -XX:MaxPermSize=n 设置持久代的大小
     
    收集器设置
     
    -XX:+UseSerialGC 设置串行收集器
    -XX:+UseParallelGC 设置并行收集器
    -XX:+UseParallelOldGC 设置老年代并行收集器
    -XX:+UseConcMarkSweepGC 设置并发收集器
     
    垃圾回收统计信息
    -XX:+PrintGC
    -XX:+PrintGCDetails
    -XX:+PrintGCTimeStamps
    -Xloggc:filename
     
     
    并行收集器设置
    -XX:ParallelGCThread=n设置并行收集器收集时使用的CPU数,并行收集线程数
    -XX:MaxGCPauseMillis=n设置并行收集的最大暂停时间
    -XX:GCTimeRatio=n设置垃圾回收占程序运行时间的百分比 公式为1/(1+n)
     
    并发收集器设置
    -XX:+CMSIncrementalMode:设置为增量模式,使用于单CPU
     
    年轻代大小的设置
    响应时间和吞吐量优先的都应该尽可能的设置大一点
    年老代大小的设置
    吞吐量优先的一般都是一个很大的年轻代和一个较小的年老代,这样可以尽可能的回收短期对象,减少中期对象,年老对象都是存放的生命周期长的对象。
    响应时间优先的要考虑很多因素,要看情况而定
     
    年老代可能会出现碎片,需要如下配置
    -XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩
    -XX:CMSFullGCsBeforeCompaction=0:上面设置开启的情况下,设置多少Full Gc后,对年老代进行压缩。
     
     
    JVM调优工具
     
    Jconsloe JDK自带,性能要求低
    JProfiler:功能强大,需付费
    VisualVM:JDK自带,功能强大,推荐。
     
    一般都有这些功能
    1 堆信息查看(堆空间的大小分配(年轻代,年老代,持久代))
        可以解决如下问题  查看 年老代,年轻代大小划分是否合理 ,内存泄漏,垃圾回收算法是否合理
    2 提供即时垃圾回收功能
    3 垃圾监控(长时间监控回收情况)
    4 查看堆内存,对象信息查看:数量,类型。
    5 对象引用情况查看
     
    6 线程监控,线程数量,各个线程都处在什么情况下。
    7 热点分析 CPU热点:检查系统哪些方法占用的大量CPU时间。 内存热点:检查哪些对象在系统中数量最大,可以根据找到的热点,有针对性的对系统进行优化
     8 内存泄漏检查(年老代堆空间被沾满,持久代被占满)。
     
  • 相关阅读:
    MSSQL锁定1.Isolation level (myBased)
    等待状态CXPACKET分析
    拒绝了对对象 'sp_sdidebug'(数据库 'master',所有者 'dbo')的 EXECUTE 权限
    Oracle CBO 统计信息的收集与执行计划的选择
    Oracle 11gR1 on Win7
    读书笔记 <<你的知识需要管理>>
    ORA01555 总结
    Buffer Cache Management
    如何选择合适的索引
    书评 <SQL Server 2005 Performance Tuning性能调校> 竟然能够如此的不用心........
  • 原文地址:https://www.cnblogs.com/chslch/p/4855919.html
Copyright © 2020-2023  润新知