Garbage Collection 垃圾收集
JAVA中GC的对象是堆空间和永久区
GC算法
1 引用计数法 --python
对象一旦被引用标记+1,引用失效-1,标记为0的对象不能使用
性能差,无法处理循环引用
2 标记清除 --java
从根节点开始不可达的点标记清除
3 标记压缩 --java
优化的标记清除,将存活对象压缩到内存的一端,清理其他所有空间
适用于存活对象较多场合,寻址更快,减少空间碎片,同时空闲内存是连续 的,但搬运对象会耗时间
4 复制算法 --java 新生代
高效,将内存分为两块,每次只用一块,回收时将存活对象复制到未使用的内存块,再清除原内存块中所有对象,互换角色
分代思想
根据存活周期,短命对象为新生代,长命对象为老年代
少量对象存活适合复制算法,大量适合标记清除或标记压缩
可触及性
可触及的
从根节点可以触及到这个对象
可复活的
一旦所有引用被释放,就是可复活状态
因为在finalize()中可能复活该对象
不可触及的
在finalize()后,可能会进入不可触及状态
不可触及的对象不可能复活
可以回收
public class CanReliveObj {
public static CanReliveObj obj;
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("CanReliveObj finalize called");
obj=this;
}
@Override
public String toString(){
return "I am CanReliveObj";
}
CanReliveObj finalize called
obj 可用
第二次gc
obj 是 null
public static void main(String[] args) throws InterruptedException{
obj=new CanReliveObj();
obj=null; //可复活
System.gc();
Thread.sleep(1000);
if(obj==null){
System.out.println("obj 是 null");
}else{
System.out.println("obj 可用");
}
System.out.println("第二次gc");
obj=null; //不可复活
System.gc();
Thread.sleep(1000);
if(obj==null){
System.out.println("obj 是 null");
}else{
System.out.println("obj 可用");
}
}
}
经验:避免使用finalize(),操作不慎可能导致错误。
优先级低,何时被调用, 不确定
何时发生GC不确定
可以使用try-catch-finally来替代它
根
栈中引用的对象
方法区中静态成员或者常量引用的对象(全局对象)
JNI方法栈中引用对象
Stop-The-World
Java中一种全局暂停的现象
全局停顿,所有Java代码停止,native代码可以执行,但不能和JVM交互
多半由于GC引起
Dump线程
死锁检查
堆Dump
GC时为什么会有全局停顿?
类比在聚会时打扫房间,聚会时很乱,又有新的垃圾产生,房间永远打扫不干净,只有让大家停止活动了,才能将房间打扫干净。
危害
长时间服务停止,没有响应
遇到HA系统,可能引起主备切换,严重危害生产环境。
public static class PrintThread extends Thread{
public static final long starttime=System.currentTimeMillis();
@Override
public void run(){
try{
while(true){
long t=System.currentTimeMillis()-starttime;
System.out.println("time:"+t);
Thread.sleep(100);
}
}catch(Exception e){
}
}
}
public static class MyThread extends Thread{
HashMap<Long,byte[]> map=new HashMap<Long,byte[]>();
@Override
public void run(){//工作线程
try{
while(true){
if(map.size()*512/1024/1024>=450){//大于450M时清理内存
System.out.println(“=====准备清理=====:"+map.size());
map.clear();
}
for(int i=0;i<1024;i++){
map.put(System.nanoTime(), new byte[512]);
}
Thread.sleep(1);
}
}catch(Exception e){
e.printStackTrace();
}
}
}
-Xmx512M -Xms512M -XX:+UseSerialGC -Xloggc:gc.log -XX:+PrintGCDetails -Xmn1m -XX:PretenureSizeThreshold=50 -XX:MaxTenuringThreshold=1