什么时候会触发FullGC?描述一下JVM加载class文件的原理机制?

什么时候会触发 FullGC?
除直接调用 System.gc 外,触发 Full GC 执行的情况有如下四种。 1. 旧生代空间不足 旧生代空间只有
在新生代对象转入及创建为大对象、大数组时才会出现不足的现象,当执行 Full GC 后空间仍然不
足,则抛出如下错误: java.lang.OutOfMemoryError: Java heap space 为避免以上两种状况引起
FullGC ,调优时应尽量做到让对象在 Minor GC 阶段被回收、让对象在新生代多存活一段时间及不
要创建过大的对象及数组。
2. Permanet Generation 空间满 PermanetGeneration 中存放的为一些 class 的信息等,当系统中
要加载的类、反射的类和调用的方法较多时, Permanet Generation 可能会被占满,在未配置为采
CMS GC 的情况下会执行 Full GC 。如果经过 Full GC 仍然回收不了,那么 JVM 会抛出如下错误信
息: java.lang.OutOfMemoryError: PermGen space 为避免 Perm Gen 占满造成 Full GC 现象,可
采用的方法为增大 Perm Gen 空间或转为使用 CMS GC 3. CMS GC 时出现 promotion failed concurrent mode failure 对于采用 CMS 进行旧生代 GC
程序而言,尤其要注意 GC 日志中是否有 promotion failed concurrent mode failure 两种状况,当
这两种状况出现时可能会触发 Full GC promotionfailed 是在进行 Minor GC 时, survivor space
不下、对象只能放入旧生代,而此时旧生代也放不下造成的; concurrent mode failure 是在执行
CMS GC 的过程中同时有对象要放入旧生代,而此时旧生代空间不足造成的。 应对措施为:增大
survivorspace 、旧生代空间或调低触发并发 GC 的比率,但在 JDK 5.0+ 6.0+ 的版本中有可能会由
JDK bug29 导致 CMS remark 完毕后很久才触发 sweeping 动作。对于这种状况,可通过设置 -
XX:CMSMaxAbortablePrecleanTime=5 (单位为 ms )来避免。
4. 统计得到的 Minor GC 晋升到旧生代的平均大小大于旧生代的剩余空间 这是一个较为复杂的触发
情况, Hotspot 为了避免由于新生代对象晋升到旧生代导致旧生代空间不足的现象,在进行 Minor
GC 时,做了一个判断,如果之前统计所得到的 Minor GC 晋升到旧生代的平均大小大于旧生代的剩
余空间,那么就直接触发 Full GC 。 例如程序第一次触发 MinorGC 后,有 6MB 的对象晋升到旧生
代,那么当下一次 Minor GC 发生时,首先检查旧生代的剩余空间是否大于 6MB ,如果小于 6MB
则执行 Full GC 。 当新生代采用 PSGC 时,方式稍有不同, PS GC 是在 Minor GC 后也会检查,例如上
面的例子中第一次 Minor GC 后, PS GC 会检查此时旧生代的剩余空间是否大于 6MB ,如小于,则触
发对旧生代的回收。 除了以上 4 种状况外,对于使用 RMI 来进行 RPC 或管理的 Sun JDK 应用而言,默
认情况下会一小时执行一次 Full GC 。可通过在启动时通过 - java
Dsun.rmi.dgc.client.gcInterval=3600000 来设置 Full GC 执行的间隔时间或通过 -XX:+
DisableExplicitGC 来禁止 RMI 调用 System.gc
描述一下 JVM 加载 class 文件的原理机制?
JVM 中类的装载是由类加载器( ClassLoader )和它的子类来实现的, Java 中的类加载器是一个重要
Java 运行时系统组件,它负责在运行时查找和装入类文件中的类。 由于 Java 的跨平台性,经过编
译的 Java 源程序并不是一个可执行程序,而是一个或多个类文件。当 Java 程序需要使用某个类时,
JVM 会确保这个类已经被加载、连接(验证、准备和解析)和初始化。类的加载是指把类的 .class
件中的数据读入到内存中,通常是创建一个字节数组读入 .class 文件,然后产生与所加载类对应的
Class 对象。加载完成后, Class 对象还不完整,所以此时的类还不可用。当类被加载后就进入连接
阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用
替换为直接引用)三个步骤。最后 JVM 对类进行初始化,包括: 1) 如果类存在直接的父类并且这个
类还没有被初始化,那么就先初始化父类; 2) 如果类中存在初始化语句,就依次执行这些初始化语
句。 类的加载是由类加载器完成的,类加载器包括:根加载器( BootStrap )、扩展加载器
Extension )、系统加载器( System )和用户自定义类加载器( java.lang.ClassLoader 的子
类)。从 Java 2 JDK 1.2 )开始,类加载过程采取了父亲委托机制( PDM )。 PDM 更好的保证了
Java 平台的安全性,在该机制中, JVM 自带的 Bootstrap 是根加载器,其他的加载器都有且仅有一个
父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加
载。 JVM 不会向 Java 程序提供对 Bootstrap 的引用。下面是关于几个类加载器的说明:
Bootstrap :一般用本地代码实现,负责加载 JVM 基础核心类库( rt.jar );
Extension :从 java.ext.dirs 系统属性所指定的目录中加载类库,它的父加载器是 Bootstrap System :又叫应用类加载器,其父类是 Extension 。它是应用最广泛的类加载器。它从环境变
classpath 或者系统属性 java.class.path 所指定的目录中记载类,是用户自定义加载器的默认
父加载器。

你可能感兴趣的:(java,jvm)