JVM内存布局及调优

       本博客仅供自己参考和学习,如有不足之处请担待。

      JVM本质上就是一个操作系统,主要干了件事,对Class字节码编译,内存管理。

一、Class编译,通过Classloader,隐式装载(不详细说明)

        ①加载         ②验证                 ③解析                       ④初始化

二、内存布局

   

 

       当我们把程序放到虚拟机中运行的时候,JVM不会吧我们用到的所有数据全部一股脑的,全部塞到内存中,他会按照数据的性质进行分类。这就形成了运行时的数据区域,主要有由执行引擎处理的方法区和堆。以及由JNI(本地接口)处理的虚拟机栈,本地方法栈和程序计数器。

      程序计数器,可以理解为我们在运行程序的时候,代码所在的行号的提示,这就是程序计数器最大的作用。( 特别是在**if,where,for等等这些控制跳转语句**的时候)

       java虚拟机栈:每个方法在调用时就会创建一个栈帧,每个方法从调用直至执行完成的过程,就对应一个栈帧在虚拟机中入栈到出栈的过程。

       : 是java虚拟机所管理的内存中最大的一块,java堆是被所有线程共享的一块内存区域,对象实例在这里被分配内存。是垃圾回收器(GC)管理的主要区域;

     方法区;存储已被虚拟机加载的类信息,常量,静态变量;即编译后的代码等数据;运行时常量池(runtime constant pool),也是常量池的一部分。

     直接内存:并不是虚拟机运行时数据区域的一部分,也不在java虚拟机规范中定义的内存区域。这个直接内存往往用在java IO通信上,并不是所有java程序都用上,但是这个直接内存,可以被虚拟机所管理,而且我们有参数,可以调节直接内存的大小;

    这里垃圾回收算法我就不写了。主要讲一下实战中的JVM性能调优;

 

三、内存溢出和内存泄漏

      1、内存溢出(OOM out of memory)

       原因:程序在申请内存时,JVM中没有足够的内存空间

      2、内存溢出的几种方式:

      ①、栈溢出: StackOverFlowError,常见于死递归,栈内存默认1M

      ②、堆溢出: OutOfMemory:Java heap space /  GC overhead limited exceeded

如果垃圾回收占用98%资源,但回收效率不到2%,就会发生OOM的GC overhead limited exceeded情况

      ③、方法区溢出(这里又叫永久代、垃圾回收效率很低)

                通常占用这块区域的有动态语言,Cglib/JSP等一些运行时需要编译成class字节码的,OSGI(使用多种类型的加载器)

      ④、直接内存溢出

      2、内存泄漏

      原因: 程序在申请空间后,无法释放已申请的内存,导致内存中始终被占用,如果过多的内存泄漏容易导致OOM,内存泄漏往往是代码有问题导致的。以下是内存泄漏的几种原因;

     ①、长生命周期对象持有短生命周期对象的引用。导致短生命周期对象无法GC

     ②、连接未关闭。  像数据库连接池,网络连接,IO等。。通常使用try_finally

     ③、变量作用域不合理。定义变量超过使用范围

     ④、内部类持有外部类。

     ⑤、hashcode值改变

     与内存泄漏的不同之处:

     内存溢出:是实实在在的内存不够用导致的

     内存泄漏:应该释放的对象没有释放,导致可使用内存小

      解决办法

      内存溢出:检查代码+虚拟机参数设置

      内存泄漏: 一定是代码导致的

           MAT内存泄漏分析工具:可对内存泄漏提出猜想

       几个重要的参数:

                shallow Heap :浅堆: 对象本身所占有的内存大小

                Retailed   Heap: 深堆:就是一个对象回收后,可以真实回收的大小。深堆包含那些只被它引用对象。

只要该对象被回收,该对象所单引用的对象也能被回收,引用的对象可达性没有了。其中深堆里面有两个参数,outgoing:谁引用了它,income: 它引用了谁。

 

四、JDK为我们提供的内存分析工具

      命令分析工具: 

      Jps : 虚拟机进程状态工具

      Jstat:虚拟机统计信息工具

      JInfo::java配置信息工具

      Jmap:java内存映射工具

      jhat: 虚拟机转储快照分析工具

      Jstack :java堆栈跟踪工具

     可视化工具:

     Jconsole   java监视与管理控制台

     VisualVM : 多合一故障处理工具

      怎么使用不再详细讲述,很多其他的博客都有;

 

五、JVM调优和深度了解性能优化

      1、 原则:大多数Java应用不需要GC调优,需要调优的,不是参数问题,是代码问题。在项目中,分析GC情况,从而优化代码,比调整GC参数更重要。GC优化是最后的手段。简单来说就是调节系统稳定性,优化代码。

 

      2、GC调优的目的:从MinorGC和Full GC时间和次数考虑,使用-XX:+PrintGCDetails打印GC日志;

                达到GC的最佳指标

     ①、GC的时间足够短(Minor GC执行不到50ms,Full GC执行不到1s)

     ②、GC的次数足够小( Minor GC执行不频繁,大于10秒/次,FullGC能达到10分钟/次)

      GC调优的最重要的三个选项:
     第一位:选择合适的GC回收器

     第二位:选择合适的堆大小

     第三位:选择年轻代在堆中的比重

 

      3、调优步骤(通过IDEA中VM参数添加JVM参数)

     ①、监视GC状况。在IDEA添加:-XX:+printGCDetails,打印日志。

         使用各种JVM工具,查看当前日志,分析当前JVM参数设置,并且分析当前堆内存快照和gc日志,根据实际的各区域内存划分和GC执行时间,觉得是否进行优化;

     ②、分析日志情况,判断是否需要调优。

         如果各项参数设置合理,系统没有超时日志出现,GC频率不高,GC耗时不高,那么没有必要进行GC优化;如果GC时间超过1-3秒,或者频繁GC,则必须优化;

                 注:如果满足下面的指标,则一般不需要进行GC

                   Minor GC执行时间不到50ms;

                    Minor GC执行不频繁,约10秒一次;

                  Full GC执行时间不到1s

                Full GC执行频率不算频繁,不低于10分钟1次;

     ③、调整垃圾回收类型,内存分配参数。

            如果内存分配过大或过小,或者采用的GC收集器比较慢,则应该优先调整这些参数,并且先找1台或几台机器进行beta,然后比较优化过的机器和没有优化的机器的性能对比,并有针对性的做出最后选择;

     ④、GC调优是一个不断分析的过程。根据系统运行情况具体问题具体分析

               通过不断的试验和试错,分析并找到最合适的参数

     ⑤、全面应用参数;

             如果找到了最合适的参数,则将这些参数应用到所有服务器,并进行后续跟踪。

     注: i、JVM中添加设置-XX:+printGCDetails,设置需要加一个加号。添加参数不用加号,而是用等号赋值。如-XX:MataSpaceSize=64M。如果添加参数是一个缩写形式:如-Xms500(堆初始空间调整),不需要等号。

            ii、在阅读GC日志的时候,主要关注FullGC和MinorGC的时间和次数。

    4、实战中调优(后期有时间再加)

    5、推荐配置

  1. 年轻代大小选择
    • 响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择).在此种情况下,年轻代收集发生的频率也是最小的.同时,减少到达年老代的对象.
    • 吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度.因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用.
    • 避免设置过小.当新生代设置过小时会导致:1.YGC次数更加频繁 2.可能导致YGC对象直接进入旧生代,如果此时旧生代满了,会触发FGC.
    • 响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数.如果堆设置小了,可以会造成内存碎 片,高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间.最优化的方案,一般需要参考以下数据获得:
    • 并发垃圾收集信息、持久代并发收集次数、传统GC信息、花在年轻代和年老代回收上的时间比例。

吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代.原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象

     

 

          

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值