在不同虚拟机上收集的Java AppCDS

qxsslcnc  于 2023-05-12  发布在  Java
关注(0)|答案(1)|浏览(205)

AppCDS工作的标志是包含如下语句的日志:

[22.785s][info][class,load] io.netty.handler.codec.http.HttpContentDecoder source: shared objects file
[22.785s][info][class,load] io.netty.handler.codec.http.HttpContentDecompressor source: shared objects file

另一方面,如果AppCDS不工作,日志将如下所示:

[22.516s][info][class,load] io.netty.channel.socket.ServerSocketChannel source: file:/app/libs/netty-transport-4.1.89.Final.jar
[22.516s][info][class,load] io.netty.channel.epoll.AbstractEpollServerChannel source: file:/app/libs/netty-transport-classes-epoll-4.1.89.Final.jar

例如,文件将从jar加载,这与AppCSD不太一样。
当我使用CDS转储时,检索到的第一个日志是在运行JVM的同一台机器上创建的(我遵循了this教程)。当我在同一个虚拟机上运行应用程序,但使用在另一个具有类似配置(OS系列,JVM系列)的虚拟机上创建的CDS转储时,检索第二个日志样本。第二个虚拟机是Gitlab Runner。我做了gradle任务,它实现了与教程相同的步骤来创建CDS并将其放入docker image。
下面是我运行应用程序的VM的信息:

$ cat /etc/os-release
NAME="Rocky Linux"
VERSION="8.6 (Green Obsidian)"
ID="rocky"
ID_LIKE="rhel centos fedora"
VERSION_ID="8.6"
PLATFORM_ID="platform:el8"
PRETTY_NAME="Rocky Linux 8.6 (Green Obsidian)"
ANSI_COLOR="0;32"
CPE_NAME="cpe:/o:rocky:rocky:8:GA"
HOME_URL="https://rockylinux.org/"
BUG_REPORT_URL="https://bugs.rockylinux.org/"
ROCKY_SUPPORT_PRODUCT="Rocky Linux"
ROCKY_SUPPORT_PRODUCT_VERSION="8"
REDHAT_SUPPORT_PRODUCT="Rocky Linux"
REDHAT_SUPPORT_PRODUCT_VERSION="8"
$ free -h
              total        used        free      shared  buff/cache   available
Mem:           15Gi       1.0Gi        12Gi       8.0Mi       1.9Gi        14Gi
Swap:            0B          0B          0B
$ java -version
openjdk version "17.0.7" 2023-04-18 LTS
OpenJDK Runtime Environment (Red_Hat-17.0.7.0.7-1.el8_7) (build 17.0.7+7-LTS)
OpenJDK 64-Bit Server VM (Red_Hat-17.0.7.0.7-1.el8_7) (build 17.0.7+7-LTS, mixed mode, sharing)

运行应用程序时JVM CDS相关日志,其中在该VM上进行转储:

NOTE: Picked up JDK_JAVA_OPTIONS: -Xlog:cds=debug -Xlog:class+load:file=/acds/cds.log
[0.006s][info][cds] trying to map /usr/lib/jvm/java-17-openjdk-17.0.6.0.10-3.el8_7.x86_64/lib/server/classes.jsa
[0.006s][info][cds] Opened archive /usr/lib/jvm/java-17-openjdk-17.0.6.0.10-3.el8_7.x86_64/lib/server/classes.jsa.
[0.007s][info][cds] Archive was created with UseCompressedOops = 1, UseCompressedClassPointers = 1
[0.007s][info][cds] Core region alignment: 4096
[0.007s][info][cds] Reserved archive_space_rs [0x0000000800000000 - 0x0000000800c00000] (12582912) bytes
[0.007s][info][cds] Reserved class_space_rs   [0x0000000800c00000 - 0x0000000840c00000] (1073741824) bytes
[0.007s][info][cds] Mapped static  region #0 at base 0x0000000800000000 top 0x0000000800458000 (ReadWrite)
[0.007s][info][cds] Mapped static  region #1 at base 0x0000000800458000 top 0x0000000800be1000 (ReadOnly)
[0.014s][info][cds] CDS archive was created with max heap size = 1964M, and the following configuration:
[0.014s][info][cds]     narrow_klass_base = 0x0000000800000000, narrow_klass_shift = 0
[0.014s][info][cds]     narrow_oop_mode = 0, narrow_oop_base = 0x0000000000000000, narrow_oop_shift = 0
[0.014s][info][cds]     heap range = [0x0000000085400000 - 0x0000000100000000]
[0.014s][info][cds] The current max heap size = 3956M, HeapRegion::GrainBytes = 2097152
[0.014s][info][cds]     narrow_klass_base = 0x0000000800000000, narrow_klass_shift = 0
[0.014s][info][cds]     narrow_oop_mode = 1, narrow_oop_base = 0x0000000000000000, narrow_oop_shift = 3
[0.014s][info][cds]     heap range = [0x0000000708c00000 - 0x0000000800000000]
[0.014s][info][cds] CDS heap data needs to be relocated because the archive was created with an incompatible oop encoding mode.
[0.014s][info][cds] CDS heap data relocation delta = 30064771072 bytes
[0.014s][info][cds] CDS heap data needs to be relocated lower by a further 1048576 bytes to 30063722496 to be aligned with HeapRegion::GrainBytes
[0.014s][info][cds] Trying to map heap data: region[3] at 0x00000007ffe00000, size =   536576 bytes
[0.014s][info][cds] Trying to map heap data: region[5] at 0x00000007ffd00000, size =   483328 bytes
[0.014s][info][cds] optimized module handling: enabled
[0.014s][info][cds] full module graph: enabled
[0.029s][info][cds] use_full_module_graph = true; java.base = 0x00000008004516a0
[0.029s][info][cds] patching heap embedded pointers
[0.029s][info][cds] Mapped static  region #2 at base 0x00007f4aa4d16000 top 0x00007f4aa4d4e000 (Bitmap)
[0.030s][info][cds] Unmapping region #2 at base 0x00007f4aa4d16000 (Bitmap)

这些是来自第二个虚拟机的日志,我想在其中构建AppCDS转储,然后共享它:

$ cat /etc/os-release
NAME="Rocky Linux"
VERSION="8.7 (Green Obsidian)"
ID="rocky"
ID_LIKE="rhel centos fedora"
VERSION_ID="8.7"
PLATFORM_ID="platform:el8"
PRETTY_NAME="Rocky Linux 8.7 (Green Obsidian)"
ANSI_COLOR="0;32"
LOGO="fedora-logo-icon"
CPE_NAME="cpe:/o:rocky:rocky:8:GA"
HOME_URL="https://rockylinux.org/"
BUG_REPORT_URL="https://bugs.rockylinux.org/"
ROCKY_SUPPORT_PRODUCT="Rocky-Linux-8"
ROCKY_SUPPORT_PRODUCT_VERSION="8.7"
REDHAT_SUPPORT_PRODUCT="Rocky Linux"
REDHAT_SUPPORT_PRODUCT_VERSION="8.7"
$ java -version
openjdk version "17.0.5" 2022-10-18 LTS
OpenJDK Runtime Environment (Red_Hat-17.0.5.0.8-2.el8_6) (build 17.0.5+8-LTS)
OpenJDK 64-Bit Server VM (Red_Hat-17.0.5.0.8-2.el8_6) (build 17.0.5+8-LTS, mixed mode, sharing)
$ free -h
              total        used        free      shared  buff/cache   available
Mem:          9.5Gi       1.4Gi       1.8Gi       210Mi       6.3Gi       7.5Gi
Swap:         4.9Gi        46Mi       4.9Gi

在第一个虚拟机上运行应用程序并在第二个虚拟机上进行转储时的适当CDS相关日志:

NOTE: Picked up JDK_JAVA_OPTIONS: -Xlog:cds=debug -Xlog:class+load:file=/acds/cds.log -XX:SharedArchiveFile=/acds/app-cds.jsa
[0.006s][info][cds] trying to map /opt/acds/acds.jsa
[0.006s][info][cds] Opened archive /opt/acds/acds.jsa.
[0.006s][info][cds] Archive was created with UseCompressedOops = 1, UseCompressedClassPointers = 1
[0.006s][info][cds] Core region alignment: 4096
[0.006s][info][cds] Reserved archive_space_rs [0x0000000800000000 - 0x0000000803400000] (54525952) bytes
[0.006s][info][cds] Reserved class_space_rs   [0x0000000803400000 - 0x0000000843400000] (1073741824) bytes
[0.006s][info][cds] Mapped static  region #0 at base 0x0000000800000000 top 0x00000008013cd000 (ReadWrite)
[0.006s][info][cds] Mapped static  region #1 at base 0x00000008013cd000 top 0x00000008031aa000 (ReadOnly)
[0.006s][info][cds] UseSharedSpaces: Required classpath entry does not exist: /builds/build/libs/app.jar
[0.006s][info][cds] Unmapping region #0 at base 0x0000000800000000 (ReadWrite)
[0.006s][info][cds] Unmapping region #1 at base 0x00000008013cd000 (ReadOnly)
[0.006s][debug][cds] Released shared space (archive + class) 0x0000000800000000
[0.006s][info ][cds] UseSharedSpaces: Unable to map shared spaces

主要是问题:

  • 创建CDS转储的方式、VM配置是否影响其工作?是否有要求/限制?
  • [0.006s][info][cds] UseSharedSpaces: Required classpath entry does not exist: /builds/build/libs/app.jar是什么意思
  • 在CI中提前创建AppCDS并使其可供使用的最佳方法是什么?有可能吗?

非常感谢你的帮助

ha5z0ras

ha5z0ras1#

在我用普通的bash重写了gradle任务之后,AppCDS终于工作得很好了。看起来Gradle如何处理子流程有些问题。希望这个解决方案对某人有用。如果能听到ppl如何生成AppCDS的故事,那就太好了。

#!/usr/bin/env bash

set +e;

var_jar=${1:-$(pwd)/build/libs/app.jar};
var_conf=${2:-$(pwd)/conf/development/conf.json};

function generateAppCdsClasses() {
  echo "Start generating AppCDS class list...";
  declare local var_pid;
  var_acds_list=${1:-$(pwd)/acds.list};
  java \
    -Xlog:cds=debug \
    -XX:DumpLoadedClassList="${var_acds_list}" \
    -jar ${var_jar} \
    -conf "${var_conf}" \
    -options "${var_conf}" 2>&1 &
  var_pid=$!;
  echo "AppCDS classes list PID: ${var_pid}";

  for _ in {1..30}; do
    var_response=$(curl --silent \
      -H "X-Forwarded-For: 38.102.251.12" \
      -H "User-Agent: Mozilla/5.asd2 (X11; Linux x86_64) Chrome/9${RANDOM}22${RANDOM}22.2.3" \
      "http://localhost:8080/api/healthcheck");
    var_status=$(echo "${var_response}" | jq --exit-status '.status');
    if [[ ${var_status} = "0" ]]; then
      echo "AppCDS class list was successfully generated: ";
      echo "  response: $var_response}";
      echo "  number of classes: $(wc -l < "${var_acds_list}")";
      echo "Start generating AppCDS class list...done";
      kill -9 "${var_pid}";
      return;
    fi
    sleep 1;
  done
  kill -9 "${var_pid}";
  echo "Start generating AppCDS class list...failed";
}

function generateAppCdsDump() {
  echo "Start generating AppCDS dump...";
  declare var_pid;
  var_acds_list=${1:-$(pwd)/acds.list};
  var_acds_dump=${2:-$(pwd)/acds.jsa};
  java \
    -Xlog:cds=debug \
    -Xshare:dump \
    -XX:SharedArchiveFile="${var_acds_dump}" \
    -XX:SharedClassListFile="${var_acds_list}" \
    -jar ${var_jar} \
    -conf "${var_conf}" \
    -options "${var_conf}" 2>&1 &
  sleep 10;
  du -sh "${var_acds_dump}";
  echo "Start generating AppCDS dump...done";
}

function acds() {
  var_acds_list="$(pwd)/acds.list";
  var_acds_dump="$(pwd)/acds.jsa";
  var_dest="$(pwd)/build/acds/";
  rm -rf "${var_acds_list}" "${var_acds_dump}";
  generateAppCdsClasses "${var_acds_list}";
  generateAppCdsDump "${var_acds_list}" "${var_acds_dump}";
  mkdir -p "${var_dest}";
  mv "${var_acds_dump}" "${var_dest}";
}

相关问题