Skip to content

Commit adab8a8

Browse files
[GR-51851] Add initial support for native memory tracking.
PullRequest: graal/16871
2 parents 1cbb323 + 48c64d8 commit adab8a8

File tree

65 files changed

+1410
-304
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+1410
-304
lines changed

sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/UnmanagedMemory.java

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -62,8 +62,7 @@ private UnmanagedMemory() {
6262
/**
6363
* Allocates {@code size} bytes of unmanaged memory. The content of the memory is undefined.
6464
* <p>
65-
* If {@code size} is 0, the method is allowed but not required to return the null pointer. This
66-
* method never returns a the null pointer, but instead throws a {@link OutOfMemoryError} when
65+
* This method never returns a null pointer, but instead throws an {@link OutOfMemoryError} when
6766
* allocation fails.
6867
*
6968
* @since 19.0
@@ -79,8 +78,7 @@ public static <T extends PointerBase> T malloc(UnsignedWord size) {
7978
/**
8079
* Allocates {@code size} bytes of unmanaged memory. The content of the memory is undefined.
8180
* <p>
82-
* If {@code size} is 0, the method is allowed but not required to return the null pointer. This
83-
* method never returns a the null pointer, but instead throws a {@link OutOfMemoryError} when
81+
* This method never returns a null pointer, but instead throws an {@link OutOfMemoryError} when
8482
* allocation fails.
8583
*
8684
* @since 19.0
@@ -92,8 +90,7 @@ public static <T extends PointerBase> T malloc(int size) {
9290
/**
9391
* Allocates {@code size} bytes of unmanaged memory. The content of the memory is set to 0.
9492
* <p>
95-
* If {@code size} is 0, the method is allowed but not required to return the null pointer. This
96-
* method never returns a the null pointer, but instead throws a {@link OutOfMemoryError} when
93+
* This method never returns a null pointer, but instead throws an {@link OutOfMemoryError} when
9794
* allocation fails.
9895
*
9996
* @since 19.0
@@ -109,8 +106,7 @@ public static <T extends PointerBase> T calloc(UnsignedWord size) {
109106
/**
110107
* Allocates {@code size} bytes of unmanaged memory. The content of the memory is set to 0.
111108
* <p>
112-
* If {@code size} is 0, the method is allowed but not required to return the null pointer. This
113-
* method never returns a the null pointer, but instead throws a {@link OutOfMemoryError} when
109+
* This method never returns a null pointer, but instead throws an {@link OutOfMemoryError} when
114110
* allocation fails.
115111
*
116112
* @since 19.0
@@ -124,9 +120,8 @@ public static <T extends PointerBase> T calloc(int size) {
124120
* If the new size is larger than the old size, the content of the additional memory is
125121
* undefined.
126122
* <p>
127-
* If {@code size} is 0, the method is allowed but not required to return the null pointer. This
128-
* method never returns a the null pointer, but instead throws a {@link OutOfMemoryError} when
129-
* allocation fails.
123+
* This method never returns a null pointer, but instead throws an {@link OutOfMemoryError} when
124+
* allocation fails. In that case, the old data is not deallocated and remains unchanged.
130125
*
131126
* @since 19.0
132127
*/
@@ -139,7 +134,8 @@ public static <T extends PointerBase> T realloc(T ptr, UnsignedWord size) {
139134
}
140135

141136
/**
142-
* Frees unmanaged memory that was previously allocated using methods of this class.
137+
* Frees unmanaged memory that was previously allocated using methods of this class. This method
138+
* is a no-op if the given pointer is {@code null}.
143139
*
144140
* @since 19.0
145141
*/

sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/UnmanagedMemorySupport.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -43,7 +43,7 @@
4343
import org.graalvm.word.PointerBase;
4444
import org.graalvm.word.UnsignedWord;
4545

46-
/** Implemented by operating-system specific code. */
46+
/** Implemented by platform or operating-system specific code. */
4747
public interface UnmanagedMemorySupport {
4848
<T extends PointerBase> T malloc(UnsignedWord size);
4949

substratevm/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ This changelog summarizes major changes to GraalVM Native Image.
66
* (GR-51106) Fields that are accessed via a `VarHandle` or `MethodHandle` are no longer marked as "unsafe accessed" when the `VarHandle`/`MethodHandle` can be fully intrinsified.
77
* (GR-49996) Ensure explicitly set image name (e.g., via `-o imagename`) is not accidentally overwritten by `-jar jarfile` option.
88
* (GR-48683) Together with Red Hat, we added partial support for the JFR event `OldObjectSample`.
9+
* (GR-51851) Together with Red Hat, we added initial support for native memory tracking (`--enable-monitoring=nmt`).
910
* (GR-47109) Together with Red Hat, we added support for JFR event throttling and the event `ObjectAllocationSample`.
1011
* (GR-52030) Add a stable name for `Proxy` types in Native Image. The name `$Proxy[id]` is replaced by `$Proxy.s[hashCode]` where `hashCode` is computed using the names of the `Proxy` interfaces, the name of the class loader and the name of the module if it is not a dynamic module.
1112

substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/BreakpointInterceptor.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,6 @@
6161
import java.util.concurrent.locks.ReentrantLock;
6262
import java.util.function.Supplier;
6363

64-
import com.oracle.svm.core.jni.headers.JNIMode;
65-
import jdk.graal.compiler.core.common.NumUtil;
66-
import jdk.graal.compiler.java.LambdaUtils;
6764
import org.graalvm.nativeimage.StackValue;
6865
import org.graalvm.nativeimage.UnmanagedMemory;
6966
import org.graalvm.nativeimage.c.function.CEntryPoint;
@@ -88,6 +85,7 @@
8885
import com.oracle.svm.core.jni.headers.JNIEnvironment;
8986
import com.oracle.svm.core.jni.headers.JNIFieldId;
9087
import com.oracle.svm.core.jni.headers.JNIMethodId;
88+
import com.oracle.svm.core.jni.headers.JNIMode;
9189
import com.oracle.svm.core.jni.headers.JNINativeMethod;
9290
import com.oracle.svm.core.jni.headers.JNIObjectHandle;
9391
import com.oracle.svm.core.jni.headers.JNIValue;
@@ -106,6 +104,9 @@
106104
import com.oracle.svm.jvmtiagentbase.jvmti.JvmtiInterface;
107105
import com.oracle.svm.jvmtiagentbase.jvmti.JvmtiLocationFormat;
108106

107+
import jdk.graal.compiler.core.common.NumUtil;
108+
import jdk.graal.compiler.java.LambdaUtils;
109+
109110
/**
110111
* Intercepts events of interest via breakpoints in Java code.
111112
* <p>

substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixProcessPropertiesSupport.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141

4242
import com.oracle.svm.core.BaseProcessPropertiesSupport;
4343
import com.oracle.svm.core.graal.stackvalue.UnsafeStackValue;
44-
import com.oracle.svm.core.headers.LibC;
44+
import com.oracle.svm.core.memory.UntrackedNullableNativeMemory;
4545
import com.oracle.svm.core.posix.headers.Dlfcn;
4646
import com.oracle.svm.core.posix.headers.Signal;
4747
import com.oracle.svm.core.posix.headers.Stdlib;
@@ -103,7 +103,7 @@ public String getObjectFile(PointerBase symbolAddress) {
103103
try {
104104
return CTypeConversion.toJavaString(realpath);
105105
} finally {
106-
LibC.free(realpath);
106+
UntrackedNullableNativeMemory.free(realpath);
107107
}
108108
}
109109

@@ -157,14 +157,14 @@ protected static String realpath(String path) {
157157
* pointer to it, so I have to free it.
158158
*/
159159
try (CCharPointerHolder pathHolder = CTypeConversion.toCString(path)) {
160-
final CCharPointer realpathPointer = Stdlib.realpath(pathHolder.get(), WordFactory.nullPointer());
161-
if (realpathPointer.isNull()) {
160+
CCharPointer realpath = Stdlib.realpath(pathHolder.get(), WordFactory.nullPointer());
161+
if (realpath.isNull()) {
162162
/* Failure to find a real path. */
163163
return null;
164164
} else {
165165
/* Success */
166-
final String result = CTypeConversion.toJavaString(realpathPointer);
167-
LibC.free(realpathPointer);
166+
String result = CTypeConversion.toJavaString(realpath);
167+
UntrackedNullableNativeMemory.free(realpath);
168168
return result;
169169
}
170170
}

substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixRawFileOperationSupport.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import org.graalvm.nativeimage.Platforms;
3333
import org.graalvm.nativeimage.c.type.CCharPointer;
3434
import org.graalvm.nativeimage.c.type.CTypeConversion;
35-
import org.graalvm.nativeimage.impl.UnmanagedMemorySupport;
3635
import org.graalvm.word.Pointer;
3736
import org.graalvm.word.SignedWord;
3837
import org.graalvm.word.UnsignedWord;
@@ -42,6 +41,7 @@
4241
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
4342
import com.oracle.svm.core.feature.InternalFeature;
4443
import com.oracle.svm.core.headers.LibC;
44+
import com.oracle.svm.core.memory.UntrackedNullableNativeMemory;
4545
import com.oracle.svm.core.os.AbstractRawFileOperationSupport;
4646
import com.oracle.svm.core.os.AbstractRawFileOperationSupport.RawFileOperationSupportHolder;
4747
import com.oracle.svm.core.posix.headers.Errno;
@@ -58,7 +58,7 @@ public PosixRawFileOperationSupport(boolean useNativeByteOrder) {
5858
@Override
5959
public CCharPointer allocateCPath(String path) {
6060
byte[] data = path.getBytes();
61-
CCharPointer filename = ImageSingletons.lookup(UnmanagedMemorySupport.class).malloc(WordFactory.unsigned(data.length + 1));
61+
CCharPointer filename = UntrackedNullableNativeMemory.malloc(WordFactory.unsigned(data.length + 1));
6262
if (filename.isNull()) {
6363
return WordFactory.nullPointer();
6464
}

substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinSystemPropertiesSupport.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@
3737
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
3838
import com.oracle.svm.core.feature.InternalFeature;
3939
import com.oracle.svm.core.graal.stackvalue.UnsafeStackValue;
40-
import com.oracle.svm.core.headers.LibC;
4140
import com.oracle.svm.core.jdk.SystemPropertiesSupport;
41+
import com.oracle.svm.core.memory.UntrackedNullableNativeMemory;
4242
import com.oracle.svm.core.posix.PosixSystemPropertiesSupport;
4343
import com.oracle.svm.core.posix.headers.Limits;
4444
import com.oracle.svm.core.posix.headers.Stdlib;
@@ -105,7 +105,7 @@ protected String osVersionValue() {
105105
CCharPointer osVersionStr = Foundation.systemVersionPlatform();
106106
if (osVersionStr.isNonNull()) {
107107
osVersionValue = CTypeConversion.toJavaString(osVersionStr);
108-
LibC.free(osVersionStr);
108+
UntrackedNullableNativeMemory.free(osVersionStr);
109109
return osVersionValue;
110110
}
111111
} else {
@@ -120,7 +120,7 @@ protected String osVersionValue() {
120120
CCharPointer osVersionStr = Foundation.systemVersionPlatformFallback();
121121
if (osVersionStr.isNonNull()) {
122122
osVersionValue = CTypeConversion.toJavaString(osVersionStr);
123-
LibC.free(osVersionStr);
123+
UntrackedNullableNativeMemory.free(osVersionStr);
124124
return osVersionValue;
125125
}
126126
return osVersionValue = "Unknown";

substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/jvmstat/PosixPerfMemoryProvider.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,12 @@
4141

4242
import java.nio.ByteBuffer;
4343

44-
import jdk.graal.compiler.core.common.NumUtil;
4544
import org.graalvm.nativeimage.ImageSingletons;
4645
import org.graalvm.nativeimage.Platform;
4746
import org.graalvm.nativeimage.Platforms;
4847
import org.graalvm.nativeimage.StackValue;
49-
import org.graalvm.nativeimage.UnmanagedMemory;
5048
import org.graalvm.nativeimage.c.type.CCharPointer;
5149
import org.graalvm.nativeimage.c.type.CTypeConversion;
52-
import org.graalvm.nativeimage.impl.UnmanagedMemorySupport;
5350
import org.graalvm.word.Pointer;
5451
import org.graalvm.word.WordFactory;
5552

@@ -64,6 +61,8 @@
6461
import com.oracle.svm.core.jvmstat.PerfManager;
6562
import com.oracle.svm.core.jvmstat.PerfMemoryPrologue;
6663
import com.oracle.svm.core.jvmstat.PerfMemoryProvider;
64+
import com.oracle.svm.core.memory.NullableNativeMemory;
65+
import com.oracle.svm.core.nmt.NmtCategory;
6766
import com.oracle.svm.core.os.RawFileOperationSupport;
6867
import com.oracle.svm.core.os.RawFileOperationSupport.RawFileDescriptor;
6968
import com.oracle.svm.core.os.VirtualMemoryProvider;
@@ -80,6 +79,8 @@
8079
import com.oracle.svm.core.posix.headers.Signal;
8180
import com.oracle.svm.core.posix.headers.Unistd;
8281

82+
import jdk.graal.compiler.core.common.NumUtil;
83+
8384
/**
8485
* This class uses high-level JDK features at the moment. In the future, we will need to rewrite
8586
* this code so that it can be executed during the isolate startup (i.e., in uninterruptible code),
@@ -157,7 +158,7 @@ private static String getUserName(int uid) {
157158
}
158159

159160
/* Retrieve the username and copy it to a String object. */
160-
CCharPointer pwBuf = ImageSingletons.lookup(UnmanagedMemorySupport.class).malloc(WordFactory.unsigned(bufSize));
161+
CCharPointer pwBuf = NullableNativeMemory.malloc(WordFactory.unsigned(bufSize), NmtCategory.JvmStat);
161162
if (pwBuf.isNull()) {
162163
return null;
163164
}
@@ -182,7 +183,7 @@ private static String getUserName(int uid) {
182183

183184
return CTypeConversion.toJavaString(pwName);
184185
} finally {
185-
UnmanagedMemory.free(pwBuf);
186+
NullableNativeMemory.free(pwBuf);
186187
}
187188
}
188189

substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixPlatformThreads.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,16 @@
2424
*/
2525
package com.oracle.svm.core.posix.thread;
2626

27-
import org.graalvm.nativeimage.ImageSingletons;
2827
import org.graalvm.nativeimage.Platform;
2928
import org.graalvm.nativeimage.Platform.HOSTED_ONLY;
3029
import org.graalvm.nativeimage.Platforms;
3130
import org.graalvm.nativeimage.StackValue;
32-
import org.graalvm.nativeimage.UnmanagedMemory;
3331
import org.graalvm.nativeimage.c.function.CFunctionPointer;
3432
import org.graalvm.nativeimage.c.struct.SizeOf;
3533
import org.graalvm.nativeimage.c.type.CTypeConversion;
3634
import org.graalvm.nativeimage.c.type.CTypeConversion.CCharPointerHolder;
3735
import org.graalvm.nativeimage.c.type.VoidPointer;
3836
import org.graalvm.nativeimage.c.type.WordPointer;
39-
import org.graalvm.nativeimage.impl.UnmanagedMemorySupport;
4037
import org.graalvm.word.Pointer;
4138
import org.graalvm.word.PointerBase;
4239
import org.graalvm.word.UnsignedWord;
@@ -50,6 +47,8 @@
5047
import com.oracle.svm.core.annotate.TargetClass;
5148
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
5249
import com.oracle.svm.core.graal.stackvalue.UnsafeStackValue;
50+
import com.oracle.svm.core.memory.NativeMemory;
51+
import com.oracle.svm.core.nmt.NmtCategory;
5352
import com.oracle.svm.core.posix.PosixUtils;
5453
import com.oracle.svm.core.posix.headers.Errno;
5554
import com.oracle.svm.core.posix.headers.Pthread;
@@ -321,7 +320,7 @@ final class PosixParker extends Parker {
321320
// Allocate mutex and condition in a single step so that they are adjacent in memory.
322321
UnsignedWord mutexSize = SizeOf.unsigned(pthread_mutex_t.class);
323322
UnsignedWord condSize = SizeOf.unsigned(pthread_cond_t.class);
324-
Pointer memory = UnmanagedMemory.malloc(mutexSize.add(condSize.multiply(2)));
323+
Pointer memory = NativeMemory.malloc(mutexSize.add(condSize.multiply(2)), NmtCategory.Threading);
325324
mutex = (pthread_mutex_t) memory;
326325
relativeCond = (pthread_cond_t) memory.add(mutexSize);
327326
absoluteCond = (pthread_cond_t) memory.add(mutexSize).add(condSize);
@@ -437,7 +436,7 @@ protected void release() {
437436

438437
status = Pthread.pthread_mutex_destroy(mutex);
439438
assert status == 0;
440-
ImageSingletons.lookup(UnmanagedMemorySupport.class).free(mutex);
439+
NativeMemory.free(mutex);
441440
mutex = WordFactory.nullPointer();
442441
}
443442
}

substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsSystemPropertiesSupport.java

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,9 @@
4545
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
4646
import com.oracle.svm.core.feature.InternalFeature;
4747
import com.oracle.svm.core.graal.stackvalue.UnsafeStackValue;
48-
import com.oracle.svm.core.headers.LibC;
4948
import com.oracle.svm.core.jdk.SystemPropertiesSupport;
49+
import com.oracle.svm.core.memory.NullableNativeMemory;
50+
import com.oracle.svm.core.nmt.NmtCategory;
5051
import com.oracle.svm.core.util.VMError;
5152
import com.oracle.svm.core.windows.headers.FileAPI;
5253
import com.oracle.svm.core.windows.headers.LibLoaderAPI;
@@ -245,29 +246,29 @@ public Pair<String, String> getOsNameAndVersion() {
245246
break;
246247
}
247248

248-
VoidPointer versionInfo = LibC.malloc(WordFactory.unsigned(versionSize));
249+
VoidPointer versionInfo = NullableNativeMemory.malloc(WordFactory.unsigned(versionSize), NmtCategory.Internal);
249250
if (versionInfo.isNull()) {
250251
break;
251252
}
253+
try {
254+
if (WinVer.GetFileVersionInfoW(kernel32Path, 0, versionSize, versionInfo) == 0) {
255+
break;
256+
}
252257

253-
if (WinVer.GetFileVersionInfoW(kernel32Path, 0, versionSize, versionInfo) == 0) {
254-
LibC.free(versionInfo);
255-
break;
256-
}
258+
WindowsLibC.WCharPointer rootPath = NonmovableArrays.addressOf(NonmovableArrays.fromImageHeap(ROOT_PATH), 0);
259+
WordPointer fileInfoPointer = UnsafeStackValue.get(WordPointer.class);
260+
CIntPointer lengthPointer = UnsafeStackValue.get(CIntPointer.class);
261+
if (WinVer.VerQueryValueW(versionInfo, rootPath, fileInfoPointer, lengthPointer) == 0) {
262+
break;
263+
}
257264

258-
WindowsLibC.WCharPointer rootPath = NonmovableArrays.addressOf(NonmovableArrays.fromImageHeap(ROOT_PATH), 0);
259-
WordPointer fileInfoPointer = UnsafeStackValue.get(WordPointer.class);
260-
CIntPointer lengthPointer = UnsafeStackValue.get(CIntPointer.class);
261-
if (WinVer.VerQueryValueW(versionInfo, rootPath, fileInfoPointer, lengthPointer) == 0) {
262-
LibC.free(versionInfo);
263-
break;
265+
VerRsrc.VS_FIXEDFILEINFO fileInfo = fileInfoPointer.read();
266+
majorVersion = (short) (fileInfo.dwProductVersionMS() >> 16); // HIWORD
267+
minorVersion = (short) fileInfo.dwProductVersionMS(); // LOWORD
268+
buildNumber = (short) (fileInfo.dwProductVersionLS() >> 16); // HIWORD
269+
} finally {
270+
NullableNativeMemory.free(versionInfo);
264271
}
265-
266-
VerRsrc.VS_FIXEDFILEINFO fileInfo = fileInfoPointer.read();
267-
majorVersion = (short) (fileInfo.dwProductVersionMS() >> 16); // HIWORD
268-
minorVersion = (short) fileInfo.dwProductVersionMS(); // LOWORD
269-
buildNumber = (short) (fileInfo.dwProductVersionLS() >> 16); // HIWORD
270-
LibC.free(versionInfo);
271272
} while (false);
272273

273274
String osVersion = majorVersion + "." + minorVersion;

0 commit comments

Comments
 (0)