Выделение и освобождение памяти JVM в этой демонстрации объясняется? - PullRequest
4 голосов
/ 15 марта 2019

У меня есть простая демонстрация, чтобы проверить детали выделения и освобождения памяти JVM.

Версия Java

$ java -version
java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)

Демо

/**
 * VM Options: -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
 */
public class DefaultCollector {
    private static final int _1MB = 1024 * 1024;
    public static void main(String... args) {
        byte[] arr1 = new byte[2 * _1MB];
        byte[] arr2 = new byte[2 * _1MB];
        byte[] arr3 = new byte[2 * _1MB];
        byte[] arr4 = new byte[4 * _1MB];
    }
}

Журналы ГХ

[GC (Allocation Failure) [PSYoungGen: 6516K->695K(9216K)] 6516K->4791K(19456K), 0.0019189 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
Heap
 PSYoungGen      total 9216K, used 7408K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 81% used [0x00000000ff600000,0x00000000ffc8e6a8,0x00000000ffe00000)
  from space 1024K, 67% used [0x00000000ffe00000,0x00000000ffeadcb0,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 10240K, used 4096K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  object space 10240K, 40% used [0x00000000fec00000,0x00000000ff000020,0x00000000ff600000)
 Metaspace       used 3273K, capacity 4556K, committed 4864K, reserved 1056768K
  class space    used 357K, capacity 392K, committed 512K, reserved 1048576K
Disconnected from the target VM, address: '127.0.0.1:38815', transport: 'socket'

Мои вопросы

  1. -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 уже установлен и eden - 8M, from - 1M, and to - 1M представлен ясно, почему PSYoungGen total 9216K вместо 10240K?
  2. почему Allocation Failure, так как в есть еще пробелы и -XX:+HandlePromotionFailure должны быть true по умолчанию, начиная с JDK 6 и далее?
  3. почему PSYoungGen: 6516K->695K(9216K), поскольку три массива все еще живы в Молодое поколение ? это из-за ошибки выделения?
  4. почему Metaspace занимает столько памяти Metaspace used 3273K? что именно там, если не просто ввести информацию?

Я также пробовал другие комбинации:

  1. Размер: 1, 1, 1, 4 => Eden 70%, срок владения 40%

    Почему? Не все ли в раю?

  2. Размер: 1, 1, 1, 1 => Eden 80% (~ 6M), срок владения 0%

    Почему 80% (~ 6M) вместо 4M в Eden?

Обновлено

С помощью @Stephen C я обнаружил, что перед входом в систему IntelliJ Terminal as

есть вывод
/usr/lib/jvm/java-8-oracle/bin/java -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:42103,suspend=y,server=n -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -javaagent:/home/hearen/Downloads/idea-IU-183.5429.30/lib/rt/debugger-agent.jar -Dfile.encoding=UTF-8 -classpath /usr/lib/jvm/java-8-oracle/jre/lib/charsets.jar:/usr/lib/jvm/java-8-oracle/jre/lib/deploy.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/cldrdata.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/dnsns.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/jaccess.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/jfxrt.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/localedata.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/nashorn.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunec.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunjce_provider.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunpkcs11.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/zipfs.jar:/usr/lib/jvm/java-8-oracle/jre/lib/javaws.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jce.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jfr.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jfxswt.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jsse.jar:/usr/lib/jvm/java-8-oracle/jre/lib/management-agent.jar:/usr/lib/jvm/java-8-oracle/jre/lib/plugin.jar:/usr/lib/jvm/java-8-oracle/jre/lib/resources.jar:/usr/lib/jvm/java-8-oracle/jre/lib/rt.jar:/home/hearen/git/personal/about-java/target/classes:/usr/lib/jvm/java-8-oracle/lib/dt.jar:/usr/lib/jvm/java-8-oracle/lib/tools.jar:/usr/lib/jvm/java-8-oracle/lib/sa-jdi.jar:/usr/lib/jvm/java-8-oracle/lib/jconsole.jar:/usr/lib/jvm/java-8-oracle/lib/packager.jar:/usr/lib/jvm/java-8-oracle/lib/javafx-mx.jar:/usr/lib/jvm/java-8-oracle/lib/ant-javafx.jar:/home/hearen/.m2/repository/org/projectlombok/lombok/1.16.20/lombok-1.16.20.jar:/home/hearen/.m2/repository/junit/junit/4.11/junit-4.11.jar:/home/hearen/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar:/home/hearen/.m2/repository/cglib/cglib/3.2.4/cglib-3.2.4.jar:/home/hearen/.m2/repository/org/ow2/asm/asm/5.1/asm-5.1.jar:/home/hearen/.m2/repository/org/apache/ant/ant/1.9.6/ant-1.9.6.jar:/home/hearen/.m2/repository/org/apache/ant/ant-launcher/1.9.6/ant-launcher-1.9.6.jar:/home/hearen/Downloads/idea-IU-183.5429.30/lib/idea_rt.jar jvm.allocation.DefaultCollector

Затем я вручную , используя CLI для компиляции и запуска программы, как

$ javac DefaultCollector.java 
$ java -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 DefaultCollector

Выходной результат становится

Heap
 PSYoungGen      total 9216K, used 6815K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 83% used [0x00000000ff600000,0x00000000ffca7ff8,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 10240K, used 4096K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  object space 10240K, 40% used [0x00000000fec00000,0x00000000ff000010,0x00000000ff600000)
 Metaspace       used 2464K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 265K, capacity 386K, committed 512K, reserved 1048576K

Очевидно, что большой массив 4M находится непосредственно в Tenured , тогда как остальные три 2M , выделенные в Young , дают нам вышеуказанные результаты. ,

1 Ответ

5 голосов
/ 15 марта 2019

Я подозреваю, что многое из этого может быть объяснено "другими вещами" в вашей JVM.

Последняя строка вывода является свидетельством того, что у вас есть (был) агент, подключенный к вашей JVM.

Disconnected from the target VM, address: '127.0.0.1:38815', transport: 'socket'

AFAIK, агент заставит JVM загружать, компилировать и т. Д. Классы, которые ваше приложение не использует напрямую.Затем агент будет выделять объекты кучи для сокетов, буферов и т. Д. Для управления мониторингом.

Это приведет к увеличению как регулярного использования кучи, так и использования метапространства.

Я предлагаю вам повторить этот экспериментиз оболочки / командной строки без подключенного агента.Получите статистику GC, включив ведение журнала GC с помощью параметров командной строки.


Ваше обновление.

Очевидно, большой массив 4M находится непосредственно в Tenured, а остальные три 2Mвыделено в Янге, давая нам вышеупомянутые результаты.

Правильно.Существует порог, выше которого объекты размещаются непосредственно в арендуемом пространстве.Это можно настроить ....

...