除直接调用
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
所指定的目录中记载类,是用户自定义加载器的默认
父加载器。
到了这里,关于什么时候会触发FullGC?描述一下JVM加载class文件的原理机制?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!