百度面试题,大伙给点思路

wangsunng · 2024-8-7 11:57:30 · 267 次点击
写一段 java 代码,稳定的触发两次 young GC ,然后触发一次 full GC ,然后又是两次 young GC 。

关键是**稳定触发**
举报· 267 次点击
登录 注册 站外分享
19 条回复  
xuld 小成 2024-8-7 12:06:55
如果有人能回答:“如何强制触发一次 young GC”和“如何强制触发一次 full GC”。但不能回答上面的面试题。
请问这个人面试通过还是不通过?
expkzb 小成 2024-8-7 12:24:44
在 Java 中,垃圾收集器的行为通常是由 JVM 的垃圾收集策略和配置决定的,而不是由应用程序直接控制。然而,你可以使用`System.gc()`方法来建议 JVM 进行垃圾收集,但请注意,这个方法并不保证 JVM 一定会执行垃圾收集,也不保证垃圾收集的类型( Young GC 或 Full GC )。

以下是一个 Java 代码示例,它尝试触发两次 Young GC 和一次 Full GC ,然后再触发两次 Young GC 。但请记住,这只是一种尝试,实际的行为将取决于 JVM 的实现和当前的内存使用情况。

```java
public class GCTrigger {

    public static void main(String[] args) {
        // 尝试触发两次 Young GC
        for (int i = 0; i < 2; i++) {
            System.gc(); // 建议 JVM 进行垃圾收集
            System.runFinalization(); // 建议 JVM 执行可到达对象的终结方法
            try {
                // 等待一段时间,让 JVM 有机会执行垃圾收集
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }

        // 尝试触发一次 Full GC
        System.gc(); // 再次建议 JVM 进行垃圾收集

        try {
            // 等待一段时间,让 JVM 有机会执行垃圾收集
            Thread.sleep(100);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        // 尝试再次触发两次 Young GC
        for (int i = 0; i < 2; i++) {
            System.gc();
            System.runFinalization();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}
```

这段代码通过调用`System.gc()`和`System.runFinalization()`来建议 JVM 执行垃圾收集,并使用`Thread.sleep()`来等待一段时间,以便 JVM 有时间响应这些请求。然而,再次强调,这种方法不能保证垃圾收集的类型或次数。

如果你需要更精确地控制垃圾收集的行为,你可能需要使用特定的 JVM 参数来配置垃圾收集器,或者使用更高级的 JVM 监控和诊断工具来分析和优化垃圾收集的性能。
wpblank 小成 2024-8-7 12:26:30
应该是考察特定内存大小下,gc 触发时机吧,照着规则一直 new 特定大小的对象就行了吧
quantal 小成 2024-8-7 12:37:59
给一个 gpt4o 的回复
要稳定地触发两次 Young GC 、一次 Full GC ,然后再触发两次 Young GC ,可以通过精确控制堆内存分配来实现。下面是一个示例代码,该代码通过分配和释放对象来控制垃圾回收的发生:
public class GCDemo {

    private static final int _1MB = 1024 * 1024;

    public static void main(String[] args) throws InterruptedException {
        // 1. 分配足够的内存来触发两次 Young GC
        byte[] allocation1, allocation2, allocation3;
        allocation1 = new byte[2 * _1MB]; // 第一次分配
        allocation2 = new byte[2 * _1MB]; // 第二次分配
        allocation3 = new byte[2 * _1MB]; // 触发第一次 Young GC

        // 2. 再次分配内存,确保触发第二次 Young GC
        allocation1 = new byte[2 * _1MB];
        allocation2 = new byte[2 * _1MB];
        allocation3 = new byte[2 * _1MB]; // 触发第二次 Young GC

        // 3. 分配大对象,触发 Full GC
        allocation1 = new byte[4 * _1MB];
        allocation2 = new byte[4 * _1MB]; // 触发 Full GC

        // 4. 再次分配内存,确保触发两次 Young GC
        allocation1 = new byte[2 * _1MB];
        allocation2 = new byte[2 * _1MB];
        allocation3 = new byte[2 * _1MB]; // 触发第三次 Young GC

        allocation1 = new byte[2 * _1MB];
        allocation2 = new byte[2 * _1MB];
        allocation3 = new byte[2 * _1MB]; // 触发第四次 Young GC

        // 程序结束,等待手动触发 Full GC
        System.gc();
    }
}
为了确保该代码按预期运行,你需要使用适当的 JVM 参数来配置堆大小和垃圾收集器。例如:
java -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:+UseSerialGC GCDemo
yuankui 小成 2024-8-7 12:41:19
茴香豆雕花
pangdundun996 初学 2024-8-7 12:53:57
问了一下 GPT ,大致思路是:
1 )设置 jvm 参数:xms 、xmx 、新生代比例之类的
2 )然后代码中分配对象,先填满新生代的一半,然后继续分配两次,触发两次 young gc
3 )取消所有对象引用,触发 gull gc ,因为后续两次分配导致有对象晋升到 old gen
4 )重复第二步,触发两次 young gc
中间通过 sleep 来控制流程
JasonLaw 小成 2024-8-7 13:04:35
这样的问题有什么意义?😅
jixiangqd 小成 2024-8-7 14:12:05
@JasonLaw #9 意义还是有点,看你是否了解 jvm 的内存管理细节,而且有实践经验
FreeWong 初学 2024-8-7 14:21:37
这么在意垃圾回收,还用什么 java
12下一页
返回顶部