垃圾
内存不再有用的对象,占用的内存应该释放,将不再有用的对象清除出内存的工作成为垃圾收集
垃圾标准:
对于非线程来说,当所有活动线程都不可能访问到该对象时,该对象便成了垃圾
对于线程来说,除了满足第一条标准之外,还要求此线程本身已经死亡或者处于新建的状态
使对象称为垃圾的方法:
将对象引用指向null或者将对象引用指向别的对象
内存中之前对象存储地址成了无主对象,就会被垃圾回收器回收
随着语句块或者方法体退出局部引用消亡
超出了作用范围
没有引用指向的对象就是垃圾,有引用指向的对象不是垃圾
这句话错误,有引用指向的对象也有可能是垃圾,关键看对象能不能被活动线程访问到
垃圾收集器
垃圾收集器是一个后台守护线程,在内存充足的情况下优先级很低,一般不出来运行,
当垃圾充斥内存,严重影响程序的执行时,优先级提高,并出来运行,清除内存
正因为如此,垃圾收集器运行时间没有保障
申请垃圾收集器运行
package com.itlwc;
public class MyRuntime {
public static void main(String[] args) throws InterruptedException {
//Runtime类中的构造方法都是私有的,必须通过静态工厂来获取Runtime对象
Runtime runtime = Runtime.getRuntime();
System.out.println("当前JVM总内存" + runtime.totalMemory() + "字节");
System.out.println("创建10000000个垃圾对象之前JVM空闲内存为:"
+ runtime.freeMemory()+ "字节");
//休眠主线程,提供申请垃圾收集器运行的成功率
Thread.sleep(1000);//主线程休眠1000毫秒
for (int i = 0; i < 10000000; i++) {
new String("Tom");
}
System.out.println("创建10000000个垃圾对象之后JVM空闲内存为:"
+ runtime.freeMemory()+ "字节");
System.gc();// 申请垃圾收集器运行
//休眠主线程,提供申请垃圾收集器运行的成功率
Thread.sleep(1000);//主线程休眠1000毫秒
System.out.println("使用垃圾收集器之后JVM空闲内存为:"
+ runtime.freeMemory() + "字节");
}
}
/*
当前JVM总内存2031616字节
创建10000000个垃圾对象之前JVM空闲内存为:1821656字节
创建10000000个垃圾对象之后JVM空闲内存为:1628680字节
使用垃圾收集器之后JVM空闲内存为:1880760字节
*/
finalize()
对象作为垃圾清理出内存之前,垃圾收集器会首先调用垃圾对象的finalize(),进行扫尾工作,
扫尾工作代码可以编写在finalize()中,然后再清除垃圾对象
finalize()重写
重写此方法时一般不但要编写自己类中的代码,
还应该使用super().finalize()调用父类的finalize()
子类清理代码执行父类清理代码也应该执行
finalize()的安全问题
不能在finalize()中编写恶意代码,阻止垃圾收集
在Java中,一个对象的生命周期中finalize()最多只能被执行一次,
也就是说,第一次执行垃圾收集时执行此方法阻止了垃圾收集,
第二次执行垃圾收集时不会再执行此方法,直接清楚垃圾对象