From a347ea262a926dec4894cb5b988a017ac7ba63f3 Mon Sep 17 00:00:00 2001 From: barbatos2011 <162298485+barbatos2011@users.noreply.github.com> Date: Sat, 15 Aug 2026 15:10:36 +0800 Subject: [PATCH] fix(compose): drop JDK 8 GC options that break arm64 images The published tronprotocol/java-tron image is a multi-arch manifest whose arm64 variant runs JDK 17, while the amd64 variant runs JDK 8. Every compose file hard-coded JDK 8 era GC options inside the -jvm argument: -XX:+UseConcMarkSweepGC removed in JDK 14, so the JVM refuses to start -Xloggc: mapped to unified logging in JDK 9+, which fails hard when the target directory does not yet exist On an arm64 host the quick start documented in README.md therefore exits within one second with exit code 1: Unrecognized VM option 'UseConcMarkSweepGC' Error: Could not create the Java Virtual Machine. Rather than adding a parallel set of arm64 compose files, let the image decide. bin/java-tron.vmoptions is generated per architecture at java-tron build time and already selects CMS on amd64 and ZGC on arm64, so the compose files only need to size the heap. One file now works on both architectures. single_node/README.md carried the same options in two places, including the string offered as "best practice jvm flags" for a long running FullNode, so an operator following the documentation reproduced the crash the compose change removes. Both are updated, with a note that GC selection belongs to the image. That paragraph also had a malformed entry, XX:ReservedCodeCacheSize without its leading dash, which java parses as a main class name and rejects with ClassNotFoundException; it is corrected here. GC logging is unchanged in substance but moves location: it is now written to /java-tron/gc.log inside the container as configured by the image, instead of the previous ./logs/gc.log on the host. Verified on linux/arm64 against tronprotocol/java-tron:latest (JDK 17.0.19): the node starts, serves /wallet/getnodeinfo and reports a ZHeap memory pool. The remaining option set of all ten compose files, and the new README flag string, were checked against both the arm64 image and a local JDK 8. --- metric_monitor/docker-compose/tron-fullnode.yml | 2 +- private_net/docker-compose.yml | 8 ++++---- single_node/README.md | 4 ++-- single_node/docker-compose-configure-example.yml | 2 +- single_node/docker-compose-quick-start.yml | 2 +- single_node/docker-compose.fullnode.main.yml | 2 +- single_node/docker-compose.fullnode.nile.yml | 2 +- single_node/docker-compose.fullnode.private.yml | 2 +- single_node/docker-compose.witness.private.yml | 2 +- .../docker/codepipeline/docker-compose.fullnode.main.yml | 2 +- .../docker/codepipeline/docker-compose.fullnode.nile.yml | 2 +- 11 files changed, 15 insertions(+), 15 deletions(-) diff --git a/metric_monitor/docker-compose/tron-fullnode.yml b/metric_monitor/docker-compose/tron-fullnode.yml index 6e7cc32b..c79acf98 100644 --- a/metric_monitor/docker-compose/tron-fullnode.yml +++ b/metric_monitor/docker-compose/tron-fullnode.yml @@ -18,6 +18,6 @@ services: - ../output-directory:/java-tron/output-directory # mount a local directory to make the block data persistent. - ../logs:/java-tron/logs command: > - -jvm "{-Xmx14g -Xmn1g -XX:MaxDirectMemorySize=1G -XX:+UseConcMarkSweepGC -XX:+PrintGC -Xloggc:./logs/gc.log }" -c ./conf/main_net_config_open_metric.conf + -jvm "{-Xmx14g -Xmn1g -XX:MaxDirectMemorySize=1G}" -c ./conf/main_net_config_open_metric.conf environment: - TZ=Asia/Shanghai # The metric and log date will be changed accordingly diff --git a/private_net/docker-compose.yml b/private_net/docker-compose.yml index defbf00e..682091c6 100644 --- a/private_net/docker-compose.yml +++ b/private_net/docker-compose.yml @@ -17,7 +17,7 @@ services: - ./datadir:/java-tron/data # mount a local directory to make the blocks data persistent. - ./logs/tron-witness1:/java-tron/logs # map to host logs command: > - -jvm "{-Xmx12g -Xmn2g -XX:+UseConcMarkSweepGC -Xloggc:./logs/gc.log}" -c /java-tron/conf/private_net_config_witness1.conf -d /java-tron/data -w + -jvm "{-Xmx12g -Xmn2g}" -c /java-tron/conf/private_net_config_witness1.conf -d /java-tron/data -w # tron-witness2: # image: tronprotocol/java-tron:latest @@ -32,7 +32,7 @@ services: # - ../conf:/java-tron/conf # - ./logs/tron-witness2:/java-tron/logs # command: > - # -jvm "{-Xmx12g -Xmn2g -XX:+UseConcMarkSweepGC -Xloggc:./logs/gc.log}" + # -jvm "{-Xmx12g -Xmn2g}" # -c /java-tron/conf/private_net_config_witness2.conf # -w tron-node1: @@ -48,7 +48,7 @@ services: - ../conf:/java-tron/conf - ./logs/tron-node1:/java-tron/logs command: > - -jvm "{-Xmx12g -Xmn2g -XX:+UseConcMarkSweepGC -Xloggc:./logs/gc.log}" -c /java-tron/conf/private_net_config_others.conf + -jvm "{-Xmx12g -Xmn2g}" -c /java-tron/conf/private_net_config_others.conf # tron-node2: # image: tronprotocol/java-tron:latest @@ -63,7 +63,7 @@ services: # - ../conf:/java-tron/conf # - ./logs/tron-node2:/java-tron/logs # command: > -# -jvm "{-Xmx12g -Xmn2g -XX:+UseConcMarkSweepGC -Xloggc:./logs/gc.log}" +# -jvm "{-Xmx12g -Xmn2g}" # -c /java-tron/conf/private_net_config_others.conf networks: tron_private_network: diff --git a/single_node/README.md b/single_node/README.md index 68824eff..02e20617 100644 --- a/single_node/README.md +++ b/single_node/README.md @@ -88,7 +88,7 @@ services: - ../logs:/java-tron/logs - ../output-directory:/java-tron/output-directory command: > - -jvm "{-Xmx14g -Xms12g -XX:+UseConcMarkSweepGC}" + -jvm "{-Xmx14g -Xms12g}" -c /java-tron/conf/main_net_config.conf -d /java-tron/output-directory -w @@ -98,7 +98,7 @@ In the example above, the host file `../conf/main_net_config.conf` will be used. Logs generated by docker container will be mapped to your `../logs/mainnet/logs`. Flags in `command` are used for java-tron start-up arguments: -- `-jvm` used for java virtual machine, the parameters must be enclosed in double quotes and braces. `"{-Xmx14g -Xms12g}"` sets the maximum and initial heap size to 14GB and 12GB respectively. If you want to set up a long run FullNode, please use the best practice jvm flags with `"{-Xmx14g -Xmn2g XX:ReservedCodeCacheSize=256m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -XX:MaxDirectMemorySize=1G -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log -XX:+UseConcMarkSweepGC -XX:NewRatio=2 -XX:+CMSScavengeBeforeRemark -XX:+ParallelRefProcEnabled -XX:+HeapDumpOnOutOfMemoryError -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70}"`. +- `-jvm` used for java virtual machine, the parameters must be enclosed in double quotes and braces. `"{-Xmx14g -Xms12g}"` sets the maximum and initial heap size to 14GB and 12GB respectively. If you want to set up a long run FullNode, please use the best practice jvm flags with `"{-Xmx14g -Xmn2g -XX:ReservedCodeCacheSize=256m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -XX:MaxDirectMemorySize=1G -XX:+ParallelRefProcEnabled -XX:+HeapDumpOnOutOfMemoryError}"`. Do not add garbage collector or GC logging options here. The image ships an architecture-specific `bin/java-tron.vmoptions` that already selects a collector: CMS on the amd64/JDK 8 image, ZGC on the arm64/JDK 17 image. Adding them stops the arm64 container from starting, for two different reasons: `-XX:+UseConcMarkSweepGC` was removed in JDK 14, so JDK 17 rejects it outright as an unrecognized option, while `-Xloggc:` is still accepted as a deprecated alias for unified logging but, unlike JDK 8, aborts startup when its target directory does not exist. - `-c` defines the configuration file to use. - `-d` defines the database file to use. You can mount a directory for `datadir` with snapshots. This can save time by syncing from a near-latest block number. Please refer to [**Fullnode and Lite-Fullnode**](https://tronprotocol.github.io/documentation-en/using_javatron/backup_restore/#fullnode-data-snapshot) for Mainnet data. For the Nile testnet, you can download the snapshot [here](https://database.nileex.io/). - `-w` means to start as a witness. You need to fill the `localwitness` field with private keys in configure file. Refer to the [**Run as Witness**](https://tronprotocol.github.io/documentation-en/using_javatron/installing_javatron/#startup-a-fullnode-that-produces-blocks). If you want to use keystore + password method, make sure the keystore is inside the mounted directory and remove `-d` to interact with console for password input. diff --git a/single_node/docker-compose-configure-example.yml b/single_node/docker-compose-configure-example.yml index 08469869..b733edd4 100644 --- a/single_node/docker-compose-configure-example.yml +++ b/single_node/docker-compose-configure-example.yml @@ -14,7 +14,7 @@ services: - ../logs:/java-tron/logs - ../output-directory:/java-tron/output-directory command: > - -jvm "{-Xmx14g -Xmn2g -XX:MaxDirectMemorySize=1G -XX:+UseConcMarkSweepGC -XX:+PrintGC -Xloggc:./logs/gc.log}" + -jvm "{-Xmx14g -Xmn2g -XX:MaxDirectMemorySize=1G}" -c /java-tron/conf/main_net_config.conf -d /java-tron/output-directory -w diff --git a/single_node/docker-compose-quick-start.yml b/single_node/docker-compose-quick-start.yml index f6e1950f..80a78054 100644 --- a/single_node/docker-compose-quick-start.yml +++ b/single_node/docker-compose-quick-start.yml @@ -10,4 +10,4 @@ services: - "18888:18888/udp" - "50051:50051" command: > - -jvm "{-Xmx14g -Xmn2g -XX:MaxDirectMemorySize=1G -XX:+UseConcMarkSweepGC -XX:+PrintGC -Xloggc:./logs/gc.log}" + -jvm "{-Xmx14g -Xmn2g -XX:MaxDirectMemorySize=1G}" diff --git a/single_node/docker-compose.fullnode.main.yml b/single_node/docker-compose.fullnode.main.yml index 2b1aeb2a..ff786a91 100644 --- a/single_node/docker-compose.fullnode.main.yml +++ b/single_node/docker-compose.fullnode.main.yml @@ -15,6 +15,6 @@ services: - ../output-directory/mainnet:/java-tron/output-directory command: - -jvm - - "{-Xmx14g -Xmn2g -XX:MaxDirectMemorySize=1G -XX:+UseConcMarkSweepGC -XX:+PrintGC -Xloggc:./logs/gc.log }" # Using environment variable for JVM arguments + - "{-Xmx14g -Xmn2g -XX:MaxDirectMemorySize=1G}" # Using environment variable for JVM arguments - -c - /java-tron/conf/main_net_config.conf diff --git a/single_node/docker-compose.fullnode.nile.yml b/single_node/docker-compose.fullnode.nile.yml index 59e78bdc..8a590626 100644 --- a/single_node/docker-compose.fullnode.nile.yml +++ b/single_node/docker-compose.fullnode.nile.yml @@ -15,6 +15,6 @@ services: - ../output-directory/nile:/java-tron/output-directory command: - -jvm - - "{-Xmx14g -XX:+UseConcMarkSweepGC -XX:+PrintGC -Xloggc:./logs/gc.log }" # Using environment variable for JVM arguments + - "{-Xmx14g}" # Using environment variable for JVM arguments - -c - /java-tron/conf/nile_net_config.conf diff --git a/single_node/docker-compose.fullnode.private.yml b/single_node/docker-compose.fullnode.private.yml index 2c7b6551..5880caf4 100644 --- a/single_node/docker-compose.fullnode.private.yml +++ b/single_node/docker-compose.fullnode.private.yml @@ -15,6 +15,6 @@ services: - ../output-directory/private:/java-tron/output-directory command: - -jvm - - "{-Xmx4g -Xms2g -XX:+UseConcMarkSweepGC}" # Using environment variable for JVM arguments + - "{-Xmx4g -Xms2g}" # Using environment variable for JVM arguments - -c - /java-tron/conf/private_net_config_others.conf diff --git a/single_node/docker-compose.witness.private.yml b/single_node/docker-compose.witness.private.yml index 7b5575ab..1619fd34 100644 --- a/single_node/docker-compose.witness.private.yml +++ b/single_node/docker-compose.witness.private.yml @@ -15,7 +15,7 @@ services: - ../output-directory/private:/java-tron/output-directory command: - -jvm - - "{-Xmx4g -Xms2g -XX:+UseConcMarkSweepGC -XX:+PrintGC -Xloggc:./logs/gc.log}" # Using environment variable for JVM arguments + - "{-Xmx4g -Xms2g}" # Using environment variable for JVM arguments - -c - /java-tron/conf/private_net_config_witness1.conf - -w diff --git a/tools/docker/codepipeline/docker-compose.fullnode.main.yml b/tools/docker/codepipeline/docker-compose.fullnode.main.yml index a1b1d074..c61032df 100644 --- a/tools/docker/codepipeline/docker-compose.fullnode.main.yml +++ b/tools/docker/codepipeline/docker-compose.fullnode.main.yml @@ -18,6 +18,6 @@ services: - ../output-directory:/java-tron/output-directory command: - -jvm - - "{-Xmx30g -Xms24g -XX:MaxDirectMemorySize=1G -XX:+UseConcMarkSweepGC -XX:+PrintGC -Xloggc:./logs/gc.log }" # Using environment variable for JVM arguments + - "{-Xmx30g -Xms24g -XX:MaxDirectMemorySize=1G}" # Using environment variable for JVM arguments - -c - /java-tron/conf/main_net_config.conf diff --git a/tools/docker/codepipeline/docker-compose.fullnode.nile.yml b/tools/docker/codepipeline/docker-compose.fullnode.nile.yml index 501978a2..7238e95d 100644 --- a/tools/docker/codepipeline/docker-compose.fullnode.nile.yml +++ b/tools/docker/codepipeline/docker-compose.fullnode.nile.yml @@ -15,6 +15,6 @@ services: - ./output-directory/nile:/java-tron/output-directory command: - -jvm - - "{-Xmx5g -Xms4g -XX:+UseConcMarkSweepGC}" # Using environment variable for JVM arguments + - "{-Xmx5g -Xms4g}" # Using environment variable for JVM arguments - -c - /java-tron/conf/nile_net_config.conf