zoukankan      html  css  js  c++  java
  • JVM工作原理及参数说明

    JAVA堆内存划分:

      如下图:

         

      1.JVM内存划分为堆内存和非堆内存,堆内存分为年轻代(Young Generation)、老年代(Old Generation),非堆内存就一个永久代(Permanent Generation)。

      2.年轻代又分为Eden和Survivor区。Survivor区由FromSpace和ToSpace组成。 Eden区占大容量,Survivor两个区占小容量,默认比例是8:1:1。

      3.堆内存用途:存放的是对象,垃圾收集器就是收集这些对象,然后根据GC算法回收。

      4.非堆内存用途:永久代,也称为方法区,存储程序运行时长期存活的对象,比如类的元数据、方法、常量、属性等。

      注:在JDK1.8版本废弃了永久代,替代的是元空间(MetaSpace),元空间与永久代上类似,都是方法区的实现,他们最大区别是:元空间并不在JVM中,而是使用本地内存。

      元空间有两个参数需要注意:

    • MetaspaceSize :初始化元空间大小,控制发生GC阈值
    • MaxMetaspaceSize : 限制元空间大小上限,防止异常占用过多物理内存

     

    内存泄漏:

      指程序中动态分配内存给一些临时对象,但是对象不会被GC所回收,它始终占用内存。即被分配的对象可达但已无用。

     

    场景:

      1、长生命周期的对象持有短生命周期对象的引用

      这是内存泄露最常见的场景,也是代码设计中经常出现的问题。例如:在全局静态map中缓存局部变量,且没有清空操作,随着时间的推移,这个map会越来越大,造成内存泄露。

      2、修改hashset中对象的参数值,且参数是计算哈希值的字段

      当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段,否则对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中删除当前对象,造成内存泄露。

      3、机器的连接数和关闭时间设置

      长时间开启非常耗费资源的连接,也会造成内存泄露。

    内存溢出:

      指程序运行过程中无法申请到足够的内存而导致的一种错误。

      内存溢出通常发生于OLD段或Perm段垃圾回收后,仍然无内存空间容纳新的Java对象的情况。

      OOM(Out of Memory)异常常见有以下几个原因:

      1)老年代内存不足:java.lang.OutOfMemoryError:Java heap space

      2)永久代内存不足:java.lang.OutOfMemoryError:PermGen space

      3)线程栈溢出:java.lang.StackOverflowError

      线程栈时线程独有的一块内存结构,所以线程栈发生问题必定是某个线程运行时产生的错误。一般线程栈溢出是由于递归太深或方法调用层级过多导致的。

      4)代码bug,占用内存无法及时回收。

      OOM在这几个内存区都有可能出现,实际遇到OOM时,能根据异常信息定位到哪个区的内存溢出。

      可以通过添加个参数-XX:+HeapDumpOnOutMemoryError,让虚拟机在出现内存溢出异常时Dump出当前的内存堆转储快照以便事后分析。

    怎么样避免发生内存泄露和溢出:

      1、尽早释放无用对象的引用

      2、使用字符串处理,避免使用String,应大量使用StringBuffer,每一个String对象都得独立占用内存一块区域

      3、尽量少用静态变量,因为静态变量存放在永久代(方法区),永久代基本不参与垃圾回收

      4、避免在循环中创建对象

      5、开启大型文件或从数据库一次拿了太多的数据很容易造成内存溢出,所以在这些地方要大概计算一下数据量的最大值是多少,并且设定所需最小及最大的内存空间值。

    • 选择高效的GC算法,可有效减少停止应用线程时间。
    • 频繁Full GC会增加暂停时间和CPU使用率,可以加大老年代空间大小降低Full GC,但会增加回收时间,根据业务适当取舍。

    当生成新对象时,内存的申请过程如下

       

    JVM参数配置:

      -Xms  # 初始堆内存大小,默认物理内存64/1

      -Xmx  # 最大堆内存,默认物理内存4/1

      -XX:MetaspaceSize   # jdk1.8后废弃永久代(PermSize),用此参数代替

      -XX:SurvivorRatio  # 默认为8,表示Eden区域与Survivor区域的S0和S1的比例为8:1:1

      -XX:Newratio   # 设置Yong 和 Old的比例,如值为4,则Old Generation是 Yong Generation的4倍,即Yong Generation占据内存的1/5

      -XX:+DisableExplicitGC  # 禁止代码中显示调用GC

      -XX:PretenureSizeThreshold  # 大于这个参数值的对象直接分配到老年代

      -XX:MaxTenuringThreshold  # 设置的是年龄阈值,默认15(对象被复制的次数)

      -XX:CMSInitiatingOccupancyFraction  # 是指设定CMS在对内存占用率达到X%的时候开始GC

      -XX:CMSFullGCsBeforeCompaction  # 设置在执行多少次Full GC后对内存空间进行压缩整理。

      -XX:+UseTLAB  # 线程本地分配缓存区,这是一个线程专用的内存分配区域。 

      -XX:+UnlockCommercialFeatures  # 啟動飛行器參數

      -XX:FlightRecorderOptions=stackdepth=1024

    Java堆大小设置官方指导:

      Xms 和 Xmx设置为老年代存活对象的3-4倍,即FullGC之后的老年代内存占用的3-4倍

      永久代 PermSize和MaxPermSize(元空间)设置为老年代存活对象的1.2-1.5倍。

      年轻代Xmn的设置为老年代存活对象的1-1.5倍。

      老年代的内存大小设置为老年代存活对象的2-3倍。

    垃圾回收:

      清理Eden区和Survivor区叫Minor GC;清理Old区叫Major GC;清理整个堆空间—包括年轻代和老年代叫Full GC。

     努力学习中··············

    本文仅用于个人学习总结记录!

  • 相关阅读:
    BZOJ 1977: [BeiJing2010组队]次小生成树 Tree( MST + 树链剖分 + RMQ )
    BZOJ 2134: 单选错位( 期望 )
    BZOJ 1030: [JSOI2007]文本生成器( AC自动机 + dp )
    BZOJ 2599: [IOI2011]Race( 点分治 )
    BZOJ 3238: [Ahoi2013]差异( 后缀数组 + 单调栈 )
    ZOJ3732 Graph Reconstruction Havel-Hakimi定理
    HDU5653 Bomber Man wants to bomb an Array 简单DP
    HDU 5651 xiaoxin juju needs help 水题一发
    HDU 5652 India and China Origins 并查集
    HDU4725 The Shortest Path in Nya Graph dij
  • 原文地址:https://www.cnblogs.com/shiqing-zhang/p/14172777.html
Copyright © 2011-2022 走看看