Skip to content

fix(gc-log): write the GC log under ./logs and guarantee the directory - #6918

Closed
barbatos2011 wants to merge 1 commit into
tronprotocol:developfrom
barbatos2011:fix/gc-log-into-logs-dir
Closed

fix(gc-log): write the GC log under ./logs and guarantee the directory#6918
barbatos2011 wants to merge 1 commit into
tronprotocol:developfrom
barbatos2011:fix/gc-log-into-logs-dir

Conversation

@barbatos2011

Copy link
Copy Markdown
Contributor

Problem

bin/FullNode configures GC logging through gradle/java-tron.vmoptions, which points at ./gc.log. The application, meanwhile, writes tron.log under ./logs. The two logs land in different places.

That split matters most in container deployments. tron-docker and the docker/ compose files mount ./logs from the host, so tron.log is available outside the container while gc.log sits at /java-tron/gc.log and disappears when the container is removed.

Change

Point both vmoptions files at ./logs/gc.log, and create the directory in the launcher before the JVM starts.

 # gradle/java-tron.vmoptions            (x86 / JDK 8)
--Xloggc:./gc.log
+-Xloggc:./logs/gc.log

 # gradle/jdk17/java-tron.vmoptions      (arm64 / JDK 17)
--Xlog:gc,gc+heap:file=gc.log:time,tags,level:filecount=10,filesize=100M
+-Xlog:gc,gc+heap:file=./logs/gc.log:time,tags,level:filecount=10,filesize=100M
 # gradle/unixStartScript.txt
+# The GC log configured in java-tron.vmoptions is written under ./logs, next to
+# tron.log. JVM logging is initialised before the application runs, so the
+# directory has to exist by now: on JDK 9+ a missing one aborts startup.
+mkdir -p ./logs
+
 # Add default JVM options here. ...
 DEFAULT_JVM_OPTS=${defaultJvmOpts}

Why the mkdir is required, not cosmetic

java-tron creates ./logs at application startup, which is too late: JVM logging is initialised first. On JDK 9+ a missing log directory is fatal rather than a warning, so on the arm64/JDK 17 build the node refuses to start.

Verified by building the published arm64 image with only the vmoptions change applied and no mkdir:

$ docker run --rm -m 2g optb-nomkdir -jvm "{-Xmx1g}"
Invalid -Xlog option '-Xlog:gc,gc+heap:file=./logs/gc.log:time,tags,level:filecount=10,filesize=100M', see error log for details.
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
[0.000s][error][logging] Error opening log file './logs/gc.log': No such file or directory
[0.000s][error][logging] Initialization of output 'file=./logs/gc.log' using options 'filecount=10,filesize=100M' failed.

On JDK 8 the same situation is only a warning, so without the mkdir this would have been an arm64-only startup failure — exactly the kind of asymmetry that is easy to miss in review.

Verification

Both changes applied to tronprotocol/java-tron:latest (linux/arm64, openjdk 17.0.19, ZGC), run through the real entrypoint:

$ docker ps --format '{{.Status}}'
Up 18 seconds

$ docker exec <cid> ls -la /java-tron/logs/
drwxr-xr-x 2 root root  4096 db
-rw-r--r-- 1 root root  7106 gc.log        <- now here
drwxr-xr-x 2 root root  4096 grpc
-rw-r--r-- 1 root root 47779 tron.log

$ docker exec <cid> ls -la /java-tron/gc.log
ls: cannot access '/java-tron/gc.log': No such file or directory

$ docker exec <cid> head -1 /java-tron/logs/gc.log
[2026-08-15T07:24:34.520+0000][info][gc] Using The Z Garbage Collector

Scope notes

  • start.sh is unchanged. It invokes the JVM directly with its own -Xloggc:./gc.log, never reads vmoptions, and its GC log rotation (backupGcLog) expects that location. Aligning it would mean changing that rotation logic too, which is left out deliberately. Happy to fold it in if maintainers prefer the two launch paths to match.
  • gradle/windowsStartScript.txt is unchanged; it does not read vmoptions.
  • Operator-visible change: for deployments launched through bin/FullNode, gc.log moves from the working directory to ./logs/gc.log. Anything collecting it by path needs updating.

Context

Related: tronprotocol/tron-docker#127, which removes JDK 8 GC options from the compose files because they break the arm64/JDK 17 image. This PR is what lets the GC log stay visible on the host after that change.

bin/FullNode configures GC logging through gradle/java-tron.vmoptions, which
pointed at ./gc.log, while the application writes tron.log under ./logs. The
two logs ended up in different places, and in container deployments only ./logs
is normally mounted, so the GC log stayed inside the container and was lost
with it.

Point both vmoptions files at ./logs/gc.log, and create the directory in the
launcher before the JVM starts.

The mkdir is required rather than cosmetic. java-tron creates ./logs at
application startup, which is too late, because JVM logging is initialised
first. On JDK 9+ a missing directory is fatal instead of a warning, so on the
arm64/JDK 17 build the node would refuse to start:

  Invalid -Xlog option '-Xlog:gc,gc+heap:file=./logs/gc.log:...'
  Error: Could not create the Java Virtual Machine.
  [error][logging] Error opening log file './logs/gc.log': No such file or directory

Verified on linux/arm64 (JDK 17.0.19, ZGC): the node starts and gc.log appears
in ./logs next to tron.log. Without the mkdir the same configuration fails as
shown above.

start.sh is left unchanged. It invokes the JVM directly with its own
-Xloggc:./gc.log, does not read vmoptions, and its GC log rotation expects that
location.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant