2015-05-15 4 views
2

Я пытаюсь смоделировать GC в своей локальной среде. Есть ли способ сделать JVM зависанием в течение 5 минут?Как сделать JVM зависанием в течение определенного периода времени?

+2

@duffymo Как насчет других потоков JVM, которые появляются при выполнении? Они не будут спать. – Kon

+0

Что вы подразумеваете под «зависанием»? Вы можете приостановить текущий поток командой 'Thread.sleep()'. –

+0

Когда JVM обрабатывает GC, что происходит? Тот же сценарий, который я пытаюсь использовать в своей локальной среде. Thread.sleep отключает только одну нить. Как насчет оставшихся потоков? –

ответ

0

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();

Edit: После некоторых исследований, я не думаю, что это возможно: How to make another thread sleep in Java

+0

Вы не можете принудительно собрать мусор; это всего лишь предложение. – duffymo

+0

1 ТБ ОЗУ? Это все GC собирается освободиться. –

+0

'thread.sleep()' не работает, потому что вы на самом деле не вызываете метод экземпляра, а только статический метод (который должен вызывать предупреждение компилятора). 'thread.suspend()' может работать. – the8472

4

Если вы на системе Linux (большинство других Unixes будет тоже есть это), вы можете сделать

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

, чтобы приостановить весь процесс java в течение 5 минут.

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

немного менее агрессивен.

Но это будет нигде не похоже на сборщик мусора.

+0

Звучит очень хорошая идея. Я попробую в понедельник. Большое спасибо за помощь. –

+0

Я не думаю, что это сработает чем-то вроде того, что вам нужно ... имитировать GC-паузу, остановив процесс, ничего вам не поможет ИМХО. Вместо этого имитируйте утечку памяти. –

+0

Во время GC jvm будет потреблять все доступные процессоры, поэтому это не хорошая симуляция длинного GC. – Ivan

0

Разработка сборок точки доступа JVM имеет опцию UseLoopSafepoints.

С помощью этого вы можете сделать следующее:

  1. safepoints петли ограниченного
  2. написать цикл ожидания спин, что дает приращение long. это должно предотвратить VM от достижения safepoint до петли не выйдет
  3. имеют другой поток инициировать GC или вызвать Thread.getAllStackTraces(), это должно вызвать safepoint

Вместе эти вещи приостановят все темы VM, потому что они будут пытаться достигните safepoint, но safepoint будет заблокирован вашей спиновой петлей. По сути, это должно вести себя так же, как и длинный GC safepoint из-за чрезмерной работы GC.

Примечание: Я не тестировал это.

+0

Я представил полезный пример для любой HotSpot JVM – Ivan

1

Вы можете смоделировать очень длинное событие stop-the-world практически на всех JVM-системах HotSpot. HotSpot не помещает safepoints в подсчитанные циклы int, так как предполагает, что они будут заканчиваться как раз «достаточно быстро» (в этом случае серверный компилятор будет генерировать более оптимальный код цикла). Даже остановке мира придется подождать, пока этот цикл не закончится. В этом методе мы имеем очень узкую петлю, которая делает небольшие, но дорогостоящие вычисления без опроса safepoint.

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 это будет на самом деле представить время паузы для всех safepoints в журнал GC. К сожалению, выход из этой опции не имеет временных меток.
  • -XX:+PrintSafepointStatistics –XX:PrintSafepointStatisticsCount=1 эти два параметра заставят JVM сообщать причины и тайминги после каждого безопасного пункта.
Смежные вопросы