【问题标题】:How to make JVM hang for a given time period?如何让JVM在给定的时间段内挂起?
【发布时间】:2015-05-15 14:24:32
【问题描述】:

我正在尝试在本地环境中模拟 GC。有什么办法可以让 JVM 挂起 5 分钟?

【问题讨论】:

  • @duffymo 在执行时产生的其他 JVM 线程呢?他们不会睡觉。
  • “挂起”是什么意思?您可以使用Thread.sleep() 命令暂停当前线程。
  • JVM 在处理 GC 时会发生什么?我在本地环境中尝试的相同场景。 Thread.sleep 只让一个线程休眠。剩下的线程呢?
  • 我知道这不是你的问题,但过去我看到通过调整垃圾收集参数来解决与 GC 相关的问题。正确的参数可以产生很大的不同。示例(这是 2010 年的,但您会有所了解):tikalk.com/java/…

标签: java garbage-collection jvm jvm-hotspot


【解决方案1】:

如果你在 Linux 系统上(大多数其他 unix 也有这个),你可以这样做

pkill -STOP java; sleep $(( 5 * 60 )); pkill -CONT java

暂停所有java进程5分钟。

pkill -TSTP java; sleep $(( 5 * 60 )); pkill -CONT java

攻击性稍弱。

但这将垃圾收集器中断

【讨论】:

  • 这听起来是个好主意。我星期一试试。非常感谢您的帮助。
  • 我认为它不会像你需要的那样工作......通过停止进程来模拟 GC 暂停对你没有任何帮助,恕我直言。相反,模拟内存泄漏。
  • 在 GC 期间 jvm 会消耗所有可用的处理器,所以这不是一个很好的模拟 long GC。
【解决方案2】:

您可以在几乎所有 HotSpot JVM 上模拟一个非常长的 stop-the-world 事件。 HotSpot 不会将safepoints 放入计数的 int 循环中,因为它假定它们将“足够快”地终止(在这种情况下,服务器编译器将生成更优化的循环代码)。即使是停止世界也必须等到这个循环结束。在这种方法中,我们有非常紧密的循环,可以在没有安全点轮询的情况下进行小而昂贵的计算。

public static double slowpoke(int iterations) {
    double d = 0;
    for (int j = 1; j < iterations; j++) {
        d += Math.log(Math.E * j);
    }
    return d;
}

例如,您可以使用以下代码:

public class SafepointTest {

    public static double slowpoke(int iterations) {
        double d = 0;
        for (int j = 1; j < iterations; j++) {
            d += Math.log(Math.E * j);
        }
        return d;
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread() {
            @Override
            public void run() {
                double sideEffect = 0;
                for (int i = 0; i < 10000; i++) {
                    sideEffect = slowpoke(999999999);
                }
                System.out.println("result = " + sideEffect);
            }
        };
        thread.start();

        new Thread(){
            @Override
            public void run() {
                long timestamp = System.currentTimeMillis();
                while (true){
                    System.out.println("Delay " + (System.currentTimeMillis() - timestamp));
                    timestamp = System.currentTimeMillis();
                    //trigger stop-the-world 
                    System.gc();
                }
            }
        }.start();
        thread.join();
    }
}

结果:

Delay 5
Delay 4
Delay 30782
Delay 21819
Delay 21966
Delay 22812
Delay 22264
Delay 21988

为了增加延迟,只需更改 slowpoke(int iterations) 函数的参数值。

这里是有用的诊断命令:

  • -XX:+PrintGCApplicationStoppedTime 这实际上会将所有安全点的暂停时间报告到 GC 日志中。不幸的是,此选项的输出缺少时间戳。
  • -XX:+PrintSafepointStatistics –XX:PrintSafepointStatisticsCount=1 这两个选项将强制 JVM 在每个安全点之后报告原因和时间。

【讨论】:

    【解决方案3】:

    热点 JVM 的开发构建有一个名为 UseLoopSafepoints 的选项。

    使用它,您可以执行以下操作:

    1. 禁用循环安全点
    2. 编写一个递增long 的自旋等待循环。这应该可以防止虚拟机在循环退出之前到达安全点
    3. 让另一个线程发起 GC 或调用 Thread.getAllStackTraces(),这应该会触发安全点

    这些东西会一起暂停所有 VM 线程,因为它们会尝试到达安全点,但安全点会被您的自旋循环阻塞。 实际上,由于过多的 GC 工作,这应该类似于 long GC 安全点。

    注意:我还没有测试过。

    【讨论】:

    • 我为任何 HotSpot JVM 提供了一个有用的示例
    【解决方案4】:

    这对您有帮助吗https://github.com/giltene/HeapFragger。 Gil Tene 通常知道自己在做什么。

    【讨论】:

      【解决方案5】:

      JVM GC 的设计方式是您的应用程序不应“挂起”,但据我了解,您希望所有线程都休眠:

      Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
      for(Thread thread : threadSet) {
          if(thread == Thread.currentThread) //Make sure this one doesn't sleep.
              continue;
          thread.sleep({{Time in ms}});
      }
      Thread.sleep({{Time in ms}}); //Now we can make this thread sleep.
      

      完全未经测试。 你也可以强制垃圾回收:System.gc();

      编辑:经过一番研究,我认为这是不可能的: How to make another thread sleep in Java

      【讨论】:

      • 不能强制垃圾回收;这只是一个建议。
      • 1TB 内存?这就是 GC 将要释放的全部内容。
      • thread.sleep() 不起作用,因为您实际上并没有调用实例方法,而只是调用了静态方法(这应该会导致编译器警告)。 thread.suspend() 可能有用。
      • @SeetaRamayyaVadali,1TB 的内存很多。在没有过多暂停时间的情况下,热点中最先进的收集器可以处理大约 100GB(取决于内存带宽和可用线程数)。如果您必须处理如此庞大的堆,您可能需要研究 Azul 的 Zing VM 和他们的无暂停收集器。
      • @the8472 我们知道并且我们正在考虑 Azul 部分
      猜你喜欢
      • 1970-01-01
      • 2013-05-23
      • 1970-01-01
      • 1970-01-01
      • 2022-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多