详细了解JVM运行时内存( 三 )


年轻代GC触发条件

  • 当年轻代内存不足时 , 会触发Minor GC,这里的内存不足指的是Eden区的内存不足,Survivor区不会 。
  • Minor GC 会暂停其他用户的线程,等到垃圾回收结束,用户的线程才恢复 。
老年代GC触发条件
  • 老年代空间不足时,会尝试触发Minor Gc,如果空间还是不足,则会触发Major GC
  • 如果Major GC结束后 , 空间还是不足,会报OOM异常 。
  • Major GC的速度比Minor GC慢10倍以上 。
Full GC触发条件
  • 程序调用System.gc() , 会触发Full GC,但不会立即去执行 。
  • 老年代空间不足 。
  • 方法区空间不足 。
  • 通过Minor GC后仍能进入老年代的对象所占空间大于老年代剩余可用空间 。
5.元空间JDK1.8后为什么废除永久代,引入元空间
  • 在之前的永久代中,它是堆的一部分,主要是在存储类的元数据、静态变量、常量等,这些数据的大小也不太容易控制和计算,开发人员对永久代进行调优会有很多的难度 。永久代会对GC带来不必要的复杂度,回收效率偏低 。
  • 而用元空间替代永久代,这样的话可以很好的解决这个问题,因为元空间是放在本地内存上的,简而言之,只要你服务器内存还有 , 元空间基本就不会发生内存溢出等问题 。
废除永久代的好处
  • 由于类的元数据分配在本地内存上,这样就说元空间的最大分配内存就是服务器系统剩余可用内存 , 不会遇到永久代时存在的内存溢出问题 。
  • 将运行时常量池从永久代中分离出来 , 与类的元数据分开 , 提高了元数据的独立性 。
  • 将元数据从永久代剥离出来放到元空间,可以提升对元数据的管理,同时也提升GC效率 。
元空间相关参数
  • -XX:MetaspaceSize , 初始空间大?。?达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值 。
  • -XX:MaxMetaspaceSize,最大空间 , 默认是没有限制的 。如果没有使用该参数来设置类的元数据的大?。?其最大可利用空间是整个系统内存的可用空间 。JVM也可以增加本地内存空间来满足类元数据信息的存储 。但是如果没有设置最大值 , 则可能存在bug导致Metaspace的空间在不停的扩展,会导致机器的内存不足;进而可能出现swap内存被耗?。蛔钪盏贾陆讨苯颖幌低持苯觡ill掉 。如果设置了该参数,当Metaspace剩余空间不足 , 会抛出:java.lang.OutOfMemoryError: Metaspace space 。
  • -XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集 。
  • -XX:MaxMetaspaceFreeRatio,在GC之后 , 最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集 。
6.方法区6.1方法区的理解概念:
元空间、永久代是方法区具体的落地实现 。方法区看作是一块独立于Java堆的内存空间 , 它主要是用来存储所加载的类信息的,方法区是线程共享的 。
特点:
  • 方法区与堆一样是各个线程共享的内存区域 。
  • 方法区在JVM启动的时候就会被创建,并且它实际的物理内存空间和Java堆一样可以是不连续的 。
  • 方法区的大小跟堆一样,可以选择固定的大小或者动态变化 。
  • 方法区的大小决定了系统可以保存多少个类,如果系统定义了太多的类,导致方法区溢出,虚拟机仍然会报OOM异常 。
  • 关闭虚拟机就会释放方法区区域 。
6.2 方法区结构类加载器将Class文件加载到内存以后,将类的信息存储到方法区中 。
方法区中存储的内容:
  • 类型信息(域信息、方法信息)
  • 运行时常量池

详细了解JVM运行时内存

文章插图
类型信息
  • 这个类型的完整有效名称(全名 = 包名.类名)
  • 这个类型直接父类的完整有效名(对于 interface或是java.lang. Object,都没有父类)
  • 这个类型的修饰符( public, abstract,final的某个子集)
  • 这个类型直接接口的一个有序列表
域信息
域信息 , 即为类的属性,成员变量JVM必须在方法区中保存类所有的成员变量相关信息及声明顺序 。域的相关信息包括:域名称、域类型、域修饰符(pυblic、private、protected、static、final、volatile、transient的某个子集)

推荐阅读