标签:移植 get jvm root ati 核心 lock full gc 计数器
类的加载过程详细参考Class文件是如何被加载进JVM
BootstrapClassLoader(启动类加载器)
c++
编写,加载java
核心库 java.*
,构造ExtClassLoader
和AppClassLoader
。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作
ExtClassLoader (标准扩展类加载器)
java
编写,加载扩展库,如classpath
中的jre
,javax.*
或者
java.ext.dir
指定位置中的类,开发者可以直接使用标准扩展类加载器。
AppClassLoader(系统类加载器)
java编写,加载程序所在的目录,如
user.dir所在的位置的
class
CustomClassLoader(用户自定义类加载器)
java
编写,用户自定义的类加载器,可加载指定路径的class
文件
Heap,一个JVM只有一个堆内存,堆内存的大小是可以调节的。一般堆中存放的是类,方法,常量,变量,以及所有引用类型的真实对象。
堆区的逻辑结构分为两部分,非堆区和堆区,非堆区即方法区,JDK8之前叫做永久带,JDK8之后叫做元空间。堆区主要分为老年带和新生带。结构图如下:
如上图所示,堆区的主要结构可细分为:
新生区是类诞生和成长的地方,甚至会在这里死亡。当一个对象被new出来时,会首先进入Eden区,Eden区慢慢积累满了之后,触发第一次Young GC,存活对象拷贝到Survivor的from区,清空Eden区。当第二次Eden区满时,再次触发Young GC,扫描Eden区和from区,把存活的对象复制到To区,清空Eden区和from区。如果此时Survivor区的空间不够了,就会提前把对象放入老年代。
当新生带都满了时,即Young GC已经清理不出空间时,就会触发Full GC,这次重GC会将整个堆中的对象做一次GC。如果还是没有空闲的空间腾出,就会抛出异常:java.lang.OutOfMemoryError: Java heap space
由新生区过渡而来,默认的,新生区中一个对象在from区和to区来回交换15次后,如果对象最终还是存活,就放入老年代。
这个区域是常驻内存的。用来存放JDK自身携带的Class对象,Interface元数据,存储的是Java运行时的一些环境或类信息,这个区域不存在垃圾回收!当关闭JVM虚拟机就会释放这个区域的内存。
元空间:逻辑上存在,物理上不存在
给对象一个引用计数器refCount。每有一个对象引用它,计数器加1,当refCount=0的时候,表示对象不再可用。
缺点:对象循环引用时,即使两个对象都不再被访问,计数器也不为0.
如上图,从GC Roots开始向下搜索,连接的路径为引用链;GC Roots不可达的对象被判为不可用。
一般新生代(伊甸园区、幸存区)会使用复制算法,生成新的to区
优点:没有内存碎片。
缺点:内存的利用率变低,可用内存缩小为原来的一半;如果存活数量比较大,复制性能会变低。
缺点:两次扫描,严重浪费时间,会产生内存碎片。
优点:不需要额外的空间。
对于标记清除的再压缩
缺点:整理阶段存在效率问题,适合老年代这种垃圾回收频率不是很高的场景。
优点:不会产生内存碎片;不需要浪费额外的空间进行分配担保。
当前商业虚拟机都采用该算法。
新生代
:复制算法(GC后只有少量的对象存活)老年代
:标记-清除-压缩算法 (GC后对象存活率高)标签:移植 get jvm root ati 核心 lock full gc 计数器
原文地址:https://www.cnblogs.com/bGpi/p/14466843.html