JVM的运行时内存

JVM的运行时内存也叫JVM堆,从垃圾回收器的角度可以将JVM堆分为新生代,老年代和永久代,其中新生代默认占1/3堆空间,老年代占2/3堆空间,永久代的占非常少的堆空间,新生代又分为Eden区占8/10新生代区,ServivorFrom区和ServivorTo区各占1/10新生代空间。
新生代:
Eden区。ServivorFrom区和ServivorTo区,JVM新创建的对象出大对象以外会被存放在新生代中,默认占1/3堆内存空间,由于JVM会频繁创建对象,所以新生代会频繁出发啊MinorGC进行垃圾回收
1,Eden区:java新创建的对象首先会被存放在Eden区,如果创建的对象属于大对象,则直接将其分配到老年代中,大对象的定义和具体的JVM版本,堆大小,垃圾回收策略有关,一般为2kb-128kb,可以同XX:pretenureSizeThreshold设置其大小,在Eden区的内存空间不足时会触发MInorGC,对新生代进行一次垃圾回收。
2,ServivorTo区:保留上一次MinorGC时的幸存者
3.ServivorFrom区:将上一次MinorGC的幸存者作为这一次MinorGC的被扫描者。
新生代的GC过程叫做MinorGC,采用复制算法实现。
1.把Eden区和ServivorFrom区中存活的对象复制到ServivorTo区,如果某对象的年龄达到老年代的标准(对象晋升老年代的标准是由XX:MaxTenuringThreshold设置,默认为15),则将其复制到老年代,同时把这些对象的年龄加1,如果ServivorTo区的内存空间不够,则也直接将其复制到老年代,如果对象大于大对象(大小为2kb-128kb的对象属于大对象,例如通过XX:PretenureSizeThreshold=2097152设置大对象为2MB,102410242Byte=2097152Byt=2MB),则也直接将其复制到老年代
2,清空Eden区和ServivorFrom区中的对象
3,将ServivorTo区和ServivorFrom区互换,原来ServivorTo区成为下一次GC时的ServivorFrom区
老年代:
1,老年代主要存放由长生命周期的对象和大对象,老年代的GC过程叫做MajorGC。在老年代对象比较稳定,MajorGC不会频繁触发,在进行MajorGC前,JVM会进行一次MinorGC在MinorGC过后仍然出现老年代空间不足和无法找到足够大的连续空间分配给新创建的大对象时,会触发MajorGC进行垃圾回收,释放JVM的内存空间。MajorGC采用标记清除算法,该算法首先会扫描所有对象并标记存活的对象,然后回收未被标记的对象并释放空间,由于要扫描所有对象再回收,所以耗时长,这个算法容易产生碎片,在老年代没有内存空间可分配时,会抛出out of memory
永久代:
1,永久代是指内存的永久保护区域,主要存放CLass和Meta(元数据)的信息,class在类加载时被放入永久代,GC不会在程序运行期间对永久代的内存进行清理,这也导致永久代随着加载的class文件的增加而增加,在加载class文件过多时就会抛出Out of Memory异常,
需要注意的时Java8中永久代已经被元数据区代替,元数据区的作用于永久代类似,二者区别为:元数据并没有使用虚拟机的内存,而是直接使用操作系统的本地内存,因此,元数据区的大小不受JVM内存的限制,只和操作系统的内存有关,在Java8中,JVM将类的元数据放入本地内存中,将常量池和类静态变量放入java堆中,这个jvm能够加载多少元数据信息就不再由JVM的最大可用内存空间决定,而由操作系统的实际可用内存空间决定

猜你喜欢

转载自www.cnblogs.com/xiaoxiaobai0628/p/12609735.html