垃圾
- 内存不再有用的对象,占用的内存应该释放,将不再有用的对象清除出内存的工作成为垃圾收集
- 垃圾标准:
- 对于非线程来说,当所有活动线程都不可能访问到该对象时,该对象便成了垃圾
- 对于线程来说,除了满足第一条标准之外,还要求此线程本身已经死亡或者处于新建的状态
- 使对象称为垃圾的方法:
- 将对象引用指向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()最多只能被执行一次,
- 也就是说,第一次执行垃圾收集时执行此方法阻止了垃圾收集,
- 第二次执行垃圾收集时不会再执行此方法,直接清楚垃圾对象