[GR-60436] Calling System.getenv() inside an isolate causes a memory leak
Describe the Issue
Calling System.getenv() inside an isolate causes a memory leak
Using the latest version of GraalVM can resolve many issues.
- [x] I tried with the latest version of GraalVM.
GraalVM Version
openjdk 21.0.2 2024-01-16 OpenJDK Runtime Environment GraalVM CE 21.0.2+13.1 (build 21.0.2+13-jvmci-23.1-b30) OpenJDK 64-Bit Server VM GraalVM CE 21.0.2+13.1 (build 21.0.2+13-jvmci-23.1-b30, mixed mode, sharing)
Operating System and Version
Darwin MBPRO 23.6.0 Darwin Kernel Version 23.6.0: Fri Jul 5 17:55:37 PDT 2024; root:xnu-10063.141.1~2/RELEASE_ARM64_T6030 arm64
Troubleshooting Confirmation
- [x] I tried the suggestions in the troubleshooting guide.
Run Command
- Run application
TEST_LEAK=Hello ./TestLeak - Run leaks command
leaks $(pgrep -n TestLeak)
Expected Behavior
No leaks detected
Actual Behavior
Leak detected:
Process: TestLeak [53536]
Path: /Users/USER/*/TestLeak
Load Address: 0x102e54000
Identifier: TestLeak
Version: 0
Code Type: ARM64
Platform: macOS
Parent Process: zsh [18181]
Date/Time: 2024-12-05 09:08:46.120 +0100
Launch Time: 2024-12-05 09:07:55.328 +0100
OS Version: macOS 14.6 (23G80)
Report Version: 7
Analysis Tool: /Applications/Xcode.app/Contents/Developer/usr/bin/leaks
Analysis Tool Version: Xcode 16.1 (16B40)
Physical footprint: 2657K
Physical footprint (peak): 3217K
Idle exit: untracked
----
leaks Report Version: 4.0
Process 53536: 525 nodes malloced for 66 KB
Process 53536: 1 leak for 1536 total leaked bytes.
1 (1.50K) ROOT LEAK: 0x13e808200 [1536]
Steps to Reproduce
- create TestLeak class
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import org.graalvm.nativeimage.IsolateThread;
import org.graalvm.nativeimage.Isolates;
import org.graalvm.nativeimage.Isolates.CreateIsolateParameters;
import org.graalvm.nativeimage.c.function.CEntryPoint;
import org.graalvm.nativeimage.c.function.CEntryPoint.IsolateThreadContext;
public class TestLeak {
public static void main(String[] args) throws InterruptedException {
System.out.println(System.getenv("TEST_LEAK"));
var context = Isolates.createIsolate(CreateIsolateParameters.getDefault());
isolate(context);
Isolates.tearDownIsolate(context);
System.out.println("Run 'leaks $(pgrep -n TestLeak)' to see leak");
Thread.sleep(Duration.of(1, ChronoUnit.MINUTES));
}
@CEntryPoint
private static void isolate(@IsolateThreadContext IsolateThread context) {
System.out.println(System.getenv("TEST_LEAK"));
}
}
- Build native image
echo "Main-Class: TestLeak" > manifest.txt && javac TestLeak.java && jar -cvfm TestLeak.jar manifest.txt TestLeak.class && native-image -jar TestLeak.jar - Run app
TEST_LEAK=Hello ./TestLeak - In a separate terminal run leaks
leaks $(pgrep -n TestLeak)
Additional Context
No response
Run-Time Log Output and Error Messages
No response
Hi @alexfedorenchik,
Thank you for reaching out to us! I can see that you're using GraalVM CE 21.0.2+13.1 which is not the latest version of GraalVM. Could you please try testing with the latest version? You can find it here: https://github.com/graalvm/graalvm-ce-builds/releases/
java --version
openjdk 23.0.1 2024-10-15
OpenJDK Runtime Environment GraalVM CE 23.0.1+11.1 (build 23.0.1+11-jvmci-b01)
OpenJDK 64-Bit Server VM GraalVM CE 23.0.1+11.1 (build 23.0.1+11-jvmci-b01, mixed mode, sharing)
build app:
(base) afedorenchik@MBPRO test % echo "Main-Class: TestLeak" > manifest.txt && javac TestLeak.java && jar -cvfm TestLeak.jar manifest.txt TestLeak.class && native-image -jar TestLeak.jar
added manifest
adding: TestLeak.class(in = 1784) (out= 829)(deflated 53%)
========================================================================================================================
GraalVM Native Image: Generating 'TestLeak' (executable)...
========================================================================================================================
[1/8] Initializing... (3.4s @ 0.09GB)
Java version: 23.0.1+11, vendor version: GraalVM CE 23.0.1+11.1
Graal compiler: optimization level: 2, target machine: armv8-a
C compiler: cc (apple, arm64, 16.0.0)
Garbage collector: Serial GC (max heap size: 80% of RAM)
1 user-specific feature(s):
- com.oracle.svm.thirdparty.gson.GsonFeature
------------------------------------------------------------------------------------------------------------------------
Build resources:
- 26.49GB of memory (73.6% of 36.00GB system memory, determined at start)
- 12 thread(s) (100.0% of 12 available processor(s), determined at start)
[2/8] Performing analysis... [****] (3.7s @ 0.30GB)
3,300 reachable types (70.7% of 4,670 total)
3,849 reachable fields (44.2% of 8,713 total)
15,533 reachable methods (44.5% of 34,895 total)
1,045 types, 13 fields, and 140 methods registered for reflection
57 types, 56 fields, and 52 methods registered for JNI access
4 native libraries: -framework Foundation, dl, pthread, z
[3/8] Building universe... (0.7s @ 0.33GB)
[4/8] Parsing methods... [*] (0.4s @ 0.35GB)
[5/8] Inlining methods... [***] (0.4s @ 0.41GB)
[6/8] Compiling methods... [**] (3.8s @ 0.37GB)
[7/8] Laying out methods... [*] (0.8s @ 0.43GB)
[8/8] Creating image... [*] (0.9s @ 0.49GB)
5.04MB (39.76%) for code area: 8,872 compilation units
7.25MB (57.17%) for image heap: 94,988 objects and 72 resources
398.26kB ( 3.07%) for other data
12.68MB in total
------------------------------------------------------------------------------------------------------------------------
Top 10 origins of code area: Top 10 object types in image heap:
3.79MB java.base 1.37MB byte[] for code metadata
905.85kB svm.jar (Native Image) 1.27MB byte[] for java.lang.String
109.50kB java.logging 933.09kB java.lang.String
61.95kB org.graalvm.nativeimage.base 785.58kB java.lang.Class
47.16kB jdk.proxy2 283.59kB com.oracle.svm.core.hub.DynamicHubCompanion
37.66kB jdk.proxy1 281.04kB byte[] for general heap data
20.63kB org.graalvm.collections 255.70kB java.util.HashMap$Node
19.18kB jdk.internal.vm.ci 195.54kB java.lang.Object[]
11.54kB jdk.proxy3 192.41kB java.lang.String[]
8.20kB jdk.graal.compiler 186.53kB heap alignment
2.86kB for 4 more packages 1.57MB for 938 more object types
------------------------------------------------------------------------------------------------------------------------
Recommendations:
HEAP: Set max heap for improved and more predictable memory usage.
CPU: Enable more CPU features with '-march=native' for improved performance.
------------------------------------------------------------------------------------------------------------------------
0.6s (3.8% of total time) in 205 GCs | Peak RSS: 0.94GB | CPU load: 6.72
------------------------------------------------------------------------------------------------------------------------
Build artifacts:
/Users/afedorenchik/env/repos/cf-executor/test/TestLeak (executable)
========================================================================================================================
Finished generating 'TestLeak' in 14.6s.
Same result:
Process: TestLeak [77745]
Path: /Users/USER/*/TestLeak
Load Address: 0x102990000
Identifier: TestLeak
Version: 0
Code Type: ARM64
Platform: macOS
Parent Process: zsh [18181]
Date/Time: 2024-12-05 17:05:25.915 +0100
Launch Time: 2024-12-05 17:05:19.378 +0100
OS Version: macOS 14.6 (23G80)
Report Version: 7
Analysis Tool: /Applications/Xcode.app/Contents/Developer/usr/bin/leaks
Analysis Tool Version: Xcode 16.1 (16B40)
Physical footprint: 2721K
Physical footprint (peak): 3377K
Idle exit: untracked
----
leaks Report Version: 4.0
Process 77745: 525 nodes malloced for 67 KB
Process 77745: 1 leak for 1536 total leaked bytes.
1 (1.50K) ROOT LEAK: 0x13f808200 [1536]
just to note, this was not reproduced on previous version of graal and jdk
openjdk 17.0.9 2023-10-17
OpenJDK Runtime Environment GraalVM CE 17.0.9+9.1 (build 17.0.9+9-jvmci-23.0-b22)
OpenJDK 64-Bit Server VM GraalVM CE 17.0.9+9.1 (build 17.0.9+9-jvmci-23.0-b22, mixed mode, sharing)
I was able to reproduce this issue on my end as well. We will take a closer look into this and I'll make sure to keep you updated.
We had a quick look at this; to our understanding, System.getenv cannot cause any leaks.
The most likely cause here is that the tool, which is Mac-specific, is somehow not interacting properly with Native Image.