垃圾回收知识点

本文详细解析了Java中垃圾回收的目的、时机,finalize()方法的作用,以及GC的工作原理、不同类型GC的区别、JVM参数与内存监控。特别关注了堆和栈的区别,以及如何确保和监控内存使用情况。
摘要由CSDN通过智能技术生成
  1. Java中垃圾回收有什么目的?什么时候进行垃圾回收?
    1. 垃圾回收是在内存中存在没有引用的对象或超过作用域的对象时进行的
    2. 垃圾回收的目的是识别并且丢弃应用不再使用的对象来释放和重用资源
  2. 如果对象的引用被置为null,垃圾收集器是否会立即释放对象占用的内存
    1. 不会,在下一个垃圾回调周期中,这个对象将是被可回收的
    2. 也就是说并不会立即被垃圾收集器立刻回收,而是在下一次垃圾回收时才会释放其占用的内存
  3. finalize()方法什么时候被调用?析构函数(finalization)的目的是什么
    1. 垃圾回收器(garbage colector)决定回收某对象时,就会运行该对象的finalize()方法;finalize是Object类的一个方法,该方法在Object类中的声明protected void finalize() throwsThrowable { } 在垃圾回收器执行时会调用被回收对象的finalize()方法,可以覆盖此方法来实现对其资源的回收。注意:一旦垃圾回收器准备释放对象占用的内存,将首先调用该对象的finalize()方法,并且下一次垃圾回收动作发生时,才真正回收对象占用的内存空间
    2. GC本来就是内存回收了,应用还需要在finalization做什么呢? 答案是大部分时候,什么都不用做(也就是不需要重载)。只有在某些很特殊的情况下,比如你调用了一些native的方法(一般是C写的),可以要在finaliztion里去调用C的释放函数
    3. Finalizetion主要用来释放被对象占用的资源(不是指内存,而是指其他资源,比如文件(FileHandle)、端口(ports)、数据库连接(DB Connection)等)。
  4. GC 是什么?为什么要有 GC?
    1. GC 是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java 提供的 GC 功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java 语言没有提供释放已分配内存的显示操作方法。Java 程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但 JVM 可以屏蔽掉显示的垃圾回收调用
    2. 垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。在 Java 诞生初期,垃圾回收是 Java最大的亮点之一,因为服务器端的编程需要有效的防止内存泄露问题,然而时过境迁,如今 Java 的垃圾回收机制已经成为被诟病的东西。移动智能终端用户通常觉得 iOS 的系统比 Android 系统有更好的用户体验,其中一个深层次的原因就在于 Android 系统中垃圾回收的不可预知性
    3. 垃圾回收机制有很多种,包括:分代复制垃圾回收、标记垃圾回收、增量垃圾回收等方式。标准的 Java 进程既有栈又有堆。栈保存了原始型局部变量,堆保存了要创建的对象。Java 平台对堆内存回收和再利用的基本算法被称为标记和清除,但是 Java 对其进行了改进,采用“分代式垃圾收集”。这种方法会跟 Java对象的生命周期将堆内存划分为不同的区域,在垃圾收集过程中,可能会将对象移动到不同区域:
    4. 伊甸园(Eden):这是对象最初诞生的区域,并且对大多数对象来说,这里是它们唯一存在过的区域。
    5. 幸存者乐园(Survivor):从伊甸园幸存下来的对象会被挪到这里。
    6. 终身颐养园(Tenured):这是足够老的幸存对象的归宿。年轻代收集(Minor-GC)过程是不会触及这个地方的。当年轻代收集不能把对象放进终身颐养园时,就会触发一次完全收集(Major-GC),这里可能还会牵扯到压缩,以便为大对象腾出足够的空间。
  5. 与垃圾回收相关的 JVM 参数
    1. -Xms / -Xmx — 堆的初始大小 / 堆的最大大小
    2. -Xmn — 堆中年轻代的大小
    3. -XX:-DisableExplicitGC — 让 System.gc()不产生任何作用
    4. -XX:+PrintGCDetails — 打印 GC 的细节
    5. -XX:+PrintGCDateStamps — 打印 GC 操作的时间戳
    6. -XX:NewSize / XX:MaxNewSize — 设置新生代大小/新生代最大大小
    7. -XX:NewRatio — 可以设置老生代和新生代的比例
    8. -XX:PrintTenuringDistribution — 设置每次新生代 GC 后输出幸存者乐园中对象年龄的分布
    9. -XX:InitialTenuringThreshold / -XX:MaxTenuringThreshold:设置老年代阀值的初始值和最大值
    10. -XX:TargetSurvivorRatio:设置幸存区的目标使用率
  6. Serial 与 Parallel GC 之间的不同之处
    1. Serial 与 Parallel 在 GC 执行的时候都会引起 stop-the-world。它们之间主要不同 serial 收集器是默认的复制收集器,执行 GC 的时候只有一个线程,而parallel 收集器使用多个 GC 线程来执行
  7. JVM 选项 -XX:+UseCompressedOops 有什么作用?为什么要使用?
    1. 当你将你的应用从 32 位的 JVM 迁移到 64 位的 JVM 时,由于对象的指针从32 位增加到了 64 位,因此堆内存会突然增加,差不多要翻倍。这也会对 CPU缓存(容量比内存小很多)的数据产生不利的影响。因为,迁移到 64 位的 JVM主要动机在于可以指定最大堆大小,通过压缩 OOP 可以节省一定的内存。通过-XX:+UseCompressedOops 选项,JVM 会使用 32 位的 OOP,而不是 64 位的 OOP。
  8. 怎样通过 Java 程序来判断 JVM 是 32 位 还是 64位?
    1. 你可以检查某些系统属性如 sun.arch.data.model 或 os.arch 来获取该信息
  9. 32 位 JVM 和 64 位 JVM 的最大堆内存分别是多数
    1. 理论上说上 32 位的 JVM 堆内存可以到达 2^32,即 4GB,但实际上会比这个小很多。不同操作系统之间不同,如 Windows 系统大约 1.5 GB,Solaris 大约3GB。64 位 JVM 允许指定最大的堆内存,理论上可以达到 2^64,这是一个非常大的数字,实际上你可以指定堆内存大小到 100GB。甚至有的 JVM,如 Azul,堆内存到 1000G 都是可能的
  10. 解释 Java 堆空间及 GC?
    1. 当通过 Java 命令启动 Java 进程的时候,会为它分配内存。内存的一部分用于创建堆空间,当程序中创建对象的时候,就从对空间中分配内存。GC 是 JVM 内部的一个进程,回收无效对象的内存用于将来的分配
  11. 你能保证 GC 执行吗
    1. 不能,虽然你可以调用 System.gc() 或者 Runtime.gc(),但是没有办法保证 GC的执行
  12. 怎么获取 Java 程序使用的内存?堆使用的百分比?
    1. 可以通过 java.lang.Runtime 类中与内存相关方法来获取剩余的内存,总内存及最大堆内存。通过这些方法你也可以获取到堆使用的百分比及堆内存的剩余空间。Runtime.freeMemory() 方法返回剩余空间的字节数,Runtime.totalMemory()方法总内存的字节数,Runtime.maxMemory() 返回最大内存的字节数。
  13. Java 中堆和栈有什么区别
    1. JVM 中堆和栈属于不同的内存区域,使用目的也不同。栈常用于保存方法帧和局部变量,而对象总是在堆上分配。栈通常都比堆小,也不会在多个线程之间共享,而堆被整个 JVM 的所有线程共享
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值