Skip to content

Commit a3dde59

Browse files
Initial jcmd support.
1 parent dfa18cb commit a3dde59

File tree

73 files changed

+2875
-2236
lines changed

Some content is hidden

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

73 files changed

+2875
-2236
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 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
@@ -42,6 +42,8 @@
4242

4343
public interface HeapDumpSupport {
4444

45+
/** Overwrites the file if it already exists. */
4546
void dumpHeap(String outputFile, boolean live) throws java.io.IOException;
4647

48+
void dumpHeap(String outputFile, boolean live, boolean overwrite) throws java.io.IOException;
4749
}

substratevm/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ At runtime, premain runtime options are set along with main class' arguments in
99
The warning is planned to be replaced by an error in GraalVM for JDK 25.
1010
* (GR-48384) Added a GDB Python script (`gdb-debughelpers.py`) to improve the Native Image debugging experience.
1111
* (GR-49517) Add support for emitting Windows x64 unwind info. This enables stack walking in native tooling such as debuggers and profilers.
12+
* (GR-56601) Together with Red Hat, we added experimental support for `jcmd` on Linux and macOS.
1213
* (GR-57384) Preserve the origin of a resource included in a native image. The information is included in the report produced by -H:+GenerateEmbeddedResourcesFile.
1314
* (GR-58000) Support for `GetStringUTFLengthAsLong` added in JNI_VERSION_24 ([JDK-8328877](https://bugs.openjdk.org/browse/JDK-8328877))
1415
* (GR-58383) The length of the printed stack trace when using `-XX:MissingRegistrationReportingMode=Warn` can now be set with `-XX:MissingRegistrationWarnContextLines=` and its default length is now 8.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public void log(CCharPointer bytes, UnsignedWord length) {
5252
/* Save and restore errno around calls that would otherwise change errno. */
5353
final int savedErrno = LibC.errno();
5454
try {
55-
if (!PosixUtils.writeBytes(getOutputFile(), bytes, length)) {
55+
if (!PosixUtils.write(getOutputFile(), bytes, length)) {
5656
/*
5757
* We are in a low-level log routine and output failed, so there is little we can
5858
* do.

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

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,9 @@
4040
import com.oracle.svm.core.Uninterruptible;
4141
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
4242
import com.oracle.svm.core.feature.InternalFeature;
43-
import com.oracle.svm.core.headers.LibC;
4443
import com.oracle.svm.core.memory.UntrackedNullableNativeMemory;
4544
import com.oracle.svm.core.os.AbstractRawFileOperationSupport;
4645
import com.oracle.svm.core.os.AbstractRawFileOperationSupport.RawFileOperationSupportHolder;
47-
import com.oracle.svm.core.posix.headers.Errno;
4846
import com.oracle.svm.core.posix.headers.Fcntl;
4947
import com.oracle.svm.core.posix.headers.Unistd;
5048
import com.oracle.svm.core.util.VMError;
@@ -152,35 +150,14 @@ public boolean seek(RawFileDescriptor fd, long position) {
152150
@Override
153151
public boolean write(RawFileDescriptor fd, Pointer data, UnsignedWord size) {
154152
int posixFd = getPosixFileDescriptor(fd);
155-
156-
Pointer position = data;
157-
UnsignedWord remaining = size;
158-
while (remaining.aboveThan(0)) {
159-
SignedWord writtenBytes = Unistd.NoTransitions.write(posixFd, position, remaining);
160-
if (writtenBytes.equal(-1)) {
161-
if (LibC.errno() == Errno.EINTR()) {
162-
// Retry the write if it was interrupted before any bytes were written.
163-
continue;
164-
}
165-
return false;
166-
}
167-
position = position.add((UnsignedWord) writtenBytes);
168-
remaining = remaining.subtract((UnsignedWord) writtenBytes);
169-
}
170-
return true;
153+
return PosixUtils.writeUninterruptibly(posixFd, data, size);
171154
}
172155

173156
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
174157
@Override
175158
public long read(RawFileDescriptor fd, Pointer buffer, UnsignedWord bufferSize) {
176159
int posixFd = getPosixFileDescriptor(fd);
177-
178-
SignedWord readBytes;
179-
do {
180-
readBytes = Unistd.NoTransitions.read(posixFd, buffer, bufferSize);
181-
} while (readBytes.equal(-1) && LibC.errno() == Errno.EINTR());
182-
183-
return readBytes.rawValue();
160+
return PosixUtils.readUninterruptibly(posixFd, buffer, bufferSize);
184161
}
185162

186163
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242

4343
import com.oracle.svm.core.Uninterruptible;
4444
import com.oracle.svm.core.graal.stackvalue.UnsafeStackValue;
45+
import com.oracle.svm.core.headers.LibC;
46+
import com.oracle.svm.core.posix.headers.Errno;
4547
import com.oracle.svm.core.posix.headers.PosixDirectives;
4648
import com.oracle.svm.core.posix.headers.darwin.DarwinStat;
4749
import com.oracle.svm.core.posix.headers.linux.LinuxStat;
@@ -167,6 +169,26 @@ public interface stat extends PointerBase {
167169
UnsignedWord st_nlink();
168170
}
169171

172+
@Uninterruptible(reason = "LibC.errno() must not be overwritten accidentally.")
173+
public static int restartableFstat(int fd, PosixStat.stat buf) {
174+
int result;
175+
do {
176+
result = PosixStat.NoTransitions.fstat(fd, buf);
177+
} while (result == -1 && LibC.errno() == Errno.EINTR());
178+
179+
return result;
180+
}
181+
182+
@Uninterruptible(reason = "LibC.errno() must not be overwritten accidentally.")
183+
public static int restartableLstat(CCharPointer path, PosixStat.stat buf) {
184+
int result;
185+
do {
186+
result = PosixStat.NoTransitions.lstat(path, buf);
187+
} while (result == -1 && LibC.errno() == Errno.EINTR());
188+
189+
return result;
190+
}
191+
170192
@Platforms(Platform.HOSTED_ONLY.class)
171193
private PosixStat() {
172194
}

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

Lines changed: 64 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,18 @@
2424
*/
2525
package com.oracle.svm.core.posix;
2626

27+
import static com.oracle.svm.core.Uninterruptible.CALLED_FROM_UNINTERRUPTIBLE_CODE;
2728
import static com.oracle.svm.core.posix.headers.Unistd._SC_GETPW_R_SIZE_MAX;
2829

2930
import java.io.FileDescriptor;
30-
import java.io.IOException;
3131

3232
import org.graalvm.nativeimage.Platform;
3333
import org.graalvm.nativeimage.StackValue;
3434
import org.graalvm.nativeimage.c.type.CCharPointer;
3535
import org.graalvm.nativeimage.c.type.CIntPointer;
3636
import org.graalvm.nativeimage.c.type.CTypeConversion;
3737
import org.graalvm.nativeimage.c.type.CTypeConversion.CCharPointerHolder;
38+
import org.graalvm.word.Pointer;
3839
import org.graalvm.word.PointerBase;
3940
import org.graalvm.word.SignedWord;
4041
import org.graalvm.word.UnsignedWord;
@@ -48,6 +49,8 @@
4849
import com.oracle.svm.core.c.libc.LibCBase;
4950
import com.oracle.svm.core.graal.stackvalue.UnsafeStackValue;
5051
import com.oracle.svm.core.headers.LibC;
52+
import com.oracle.svm.core.hub.DynamicHub;
53+
import com.oracle.svm.core.hub.LayoutEncoding;
5154
import com.oracle.svm.core.memory.NullableNativeMemory;
5255
import com.oracle.svm.core.nmt.NmtCategory;
5356
import com.oracle.svm.core.posix.headers.Dlfcn;
@@ -61,9 +64,12 @@
6164
import com.oracle.svm.core.posix.headers.Wait;
6265
import com.oracle.svm.core.posix.headers.darwin.DarwinTime;
6366
import com.oracle.svm.core.posix.headers.linux.LinuxTime;
67+
import com.oracle.svm.core.snippets.KnownIntrinsics;
6468
import com.oracle.svm.core.util.BasedOnJDKFile;
6569
import com.oracle.svm.core.util.VMError;
6670

71+
import jdk.graal.compiler.word.Word;
72+
6773
public class PosixUtils {
6874
static String setLocale(String category, String locale) {
6975
int intCategory = getCategory(category);
@@ -140,10 +146,6 @@ public static String lastErrorString(String defaultMsg) {
140146
return errorString(errno, defaultMsg);
141147
}
142148

143-
public static IOException newIOExceptionWithLastError(String defaultMsg) {
144-
return new IOException(lastErrorString(defaultMsg));
145-
}
146-
147149
/** Return the error string for the given error number, or a default message. */
148150
public static String errorString(int errno, String defaultMsg) {
149151
String result = "";
@@ -194,25 +196,52 @@ public static int waitForProcessExit(int ppid) {
194196
* Low-level output of bytes already in native memory. This method is allocation free, so that
195197
* it can be used, e.g., in low-level logging routines.
196198
*/
197-
public static boolean writeBytes(FileDescriptor descriptor, CCharPointer bytes, UnsignedWord length) {
198-
CCharPointer curBuf = bytes;
199-
UnsignedWord curLen = length;
200-
while (curLen.notEqual(0)) {
199+
public static boolean write(FileDescriptor descriptor, CCharPointer data, UnsignedWord size) {
200+
CCharPointer position = data;
201+
UnsignedWord remaining = size;
202+
while (remaining.notEqual(0)) {
201203
int fd = getFD(descriptor);
202204
if (fd == -1) {
203205
return false;
204206
}
205207

206-
SignedWord n = Unistd.write(fd, curBuf, curLen);
207-
if (n.equal(-1)) {
208+
SignedWord writtenBytes = Unistd.write(fd, position, remaining);
209+
if (writtenBytes.equal(-1)) {
208210
if (LibC.errno() == Errno.EINTR()) {
209211
// Retry the write if it was interrupted before any bytes were written.
210212
continue;
211213
}
212214
return false;
213215
}
214-
curBuf = curBuf.addressOf(n);
215-
curLen = curLen.subtract((UnsignedWord) n);
216+
position = position.addressOf(writtenBytes);
217+
remaining = remaining.subtract((UnsignedWord) writtenBytes);
218+
}
219+
return true;
220+
}
221+
222+
@Uninterruptible(reason = "Array must not move.")
223+
public static boolean writeUninterruptibly(int fd, byte[] data) {
224+
DynamicHub hub = KnownIntrinsics.readHub(data);
225+
UnsignedWord baseOffset = LayoutEncoding.getArrayBaseOffset(hub.getLayoutEncoding());
226+
Pointer dataPtr = Word.objectToUntrackedPointer(data).add(baseOffset);
227+
return writeUninterruptibly(fd, dataPtr, WordFactory.unsigned(data.length));
228+
}
229+
230+
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
231+
public static boolean writeUninterruptibly(int fd, Pointer data, UnsignedWord size) {
232+
Pointer position = data;
233+
UnsignedWord remaining = size;
234+
while (remaining.notEqual(0)) {
235+
SignedWord writtenBytes = Unistd.NoTransitions.write(fd, position, remaining);
236+
if (writtenBytes.equal(-1)) {
237+
if (LibC.errno() == Errno.EINTR()) {
238+
// Retry the write if it was interrupted before any bytes were written.
239+
continue;
240+
}
241+
return false;
242+
}
243+
position = position.add((UnsignedWord) writtenBytes);
244+
remaining = remaining.subtract((UnsignedWord) writtenBytes);
216245
}
217246
return true;
218247
}
@@ -249,17 +278,35 @@ public static void checkStatusIs0(int status, String message) {
249278
VMError.guarantee(status == 0, message);
250279
}
251280

252-
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
253-
public static int readBytes(int fd, CCharPointer buffer, int bufferLen, int readOffset) {
281+
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
282+
public static int readUninterruptibly(int fd, Pointer buffer, int bufferLen, int bufferOffset) {
254283
int readBytes = -1;
255-
if (readOffset < bufferLen) {
284+
if (bufferOffset < bufferLen) {
256285
do {
257-
readBytes = (int) Unistd.NoTransitions.read(fd, buffer.addressOf(readOffset), WordFactory.unsigned(bufferLen - readOffset)).rawValue();
286+
readBytes = (int) Unistd.NoTransitions.read(fd, buffer.add(bufferOffset), WordFactory.unsigned(bufferLen - bufferOffset)).rawValue();
258287
} while (readBytes == -1 && LibC.errno() == Errno.EINTR());
259288
}
260289
return readBytes;
261290
}
262291

292+
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
293+
public static int readUninterruptibly(int fd, Pointer buffer, int bufferSize) {
294+
VMError.guarantee(bufferSize >= 0);
295+
long readBytes = readUninterruptibly(fd, buffer, WordFactory.unsigned(bufferSize));
296+
assert (int) readBytes == readBytes;
297+
return (int) readBytes;
298+
}
299+
300+
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
301+
public static long readUninterruptibly(int fd, Pointer buffer, UnsignedWord bufferSize) {
302+
SignedWord readBytes;
303+
do {
304+
readBytes = Unistd.NoTransitions.read(fd, buffer, bufferSize);
305+
} while (readBytes.equal(-1) && LibC.errno() == Errno.EINTR());
306+
307+
return readBytes.rawValue();
308+
}
309+
263310
// Checkstyle: stop
264311
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
265312
public static int clock_gettime(int clock_id, Time.timespec ts) {
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.core.posix.attach;
26+
27+
import org.graalvm.nativeimage.c.function.CFunction;
28+
import org.graalvm.nativeimage.c.function.CLibrary;
29+
import org.graalvm.nativeimage.c.type.CCharPointer;
30+
31+
/** C methods that are used to support the attach API. */
32+
@CLibrary(value = "libchelper", requireStatic = true)
33+
public class AttachHelper {
34+
@CFunction(value = "svm_attach_startup")
35+
public static native void startup(CCharPointer path);
36+
37+
@CFunction(value = "svm_attach_listener_cleanup")
38+
public static native void listenerCleanup(int listenerSocket, CCharPointer path);
39+
40+
/** Returns true if the socket file is valid. */
41+
@CFunction(value = "svm_attach_check_socket_file")
42+
public static native boolean checkSocketFile(CCharPointer path);
43+
44+
@CFunction(value = "svm_attach_is_init_trigger")
45+
public static native boolean isInitTrigger(CCharPointer path);
46+
47+
@CFunction(value = "svm_attach_create_listener")
48+
public static native int createListener(CCharPointer path);
49+
50+
@CFunction(value = "svm_attach_wait_for_request")
51+
public static native int waitForRequest(int listenerSocket);
52+
53+
@CFunction(value = "svm_attach_shutdown_socket")
54+
public static native void shutdownSocket(int socket);
55+
}

0 commit comments

Comments
 (0)