如何从JVM外部地址获取String?从LongBuffer地址转char*为byte[]可行吗?
char* (addressed via java.nio.LongBuffer) into a Java byte[]? Absolutely—this is possible, but it requires working with Java's low-level native/unsafe APIs since you're directly interacting with off-heap memory pointers. Let's walk through the options and critical caveats to do this safely:
Key Background First
First, confirm your LongBuffer holds a valid native memory address pointing to a char* within your process. If this address is invalid (e.g., already freed, from another process), any attempt to access it will crash the JVM immediately—so double-check validity before proceeding.
Option 1: Use sun.misc.Unsafe (or JDK 9+ jdk.internal.misc.Unsafe)
This is a quick way to prototype, but note that Unsafe is an internal, unsupported API that may change or be removed in future JDK versions.
Steps to implement:
- Retrieve the
Unsafeinstance via reflection (it’s not publicly accessible):private static Unsafe getUnsafe() throws Exception { Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); unsafeField.setAccessible(true); return (Unsafe) unsafeField.get(null); } - Extract the pointer value from your
LongBuffer:long charPtr = yourLongBuffer.get(0); // Assuming the address is stored at index 0 - Define the total byte length of your
char*data (you need to know this upfront):- If your C
charis 1-byte (ASCII/UTF-8), total bytes = number ofchars - If it’s a 2-byte wide character (like Windows
wchar_t), total bytes = number of chars × 2
- If your C
- Allocate a Java
byte[]and copy the native memory into it:Unsafe unsafe = getUnsafe(); int totalBytes = charCount * sizeofChar; // Replace with actual byte count byte[] result = new byte[totalBytes]; // Copy from native pointer to Java byte array unsafe.copyMemory(null, charPtr, result, Unsafe.ARRAY_BYTE_BASE_OFFSET, totalBytes);
Option 2: Use JNI (Recommended for Production)
JNI is the official, supported way to interact with native code, making it more stable and maintainable for production use.
Steps to implement:
- Declare a native method in your Java class:
public class NativeMemoryCopier { // Load the compiled native library (.so for Linux, .dll for Windows) static { System.loadLibrary("NativeCopier"); } /** * Copies data from a native char* to a Java byte[] * @param ptr Address of the native char* * @param charCount Number of char elements to copy * @param dest Target byte array (must be large enough to hold all bytes) */ private native void copyCharPtrToByteArray(long ptr, int charCount, byte[] dest); } - Write the corresponding C implementation:
#include <jni.h> #include <string.h> JNIEXPORT void JNICALL Java_NativeMemoryCopier_copyCharPtrToByteArray( JNIEnv *env, jobject obj, jlong ptr, jint charCount, jbyteArray dest) { // Cast the long pointer to a native char* char* nativeCharPtr = (char*)ptr; // Get a direct pointer to the Java byte array jbyte* destBytes = (*env)->GetByteArrayElements(env, dest, NULL); if (destBytes == NULL) { return; // Handle memory allocation failure } // Copy the data: adjust sizeof(char) if using wide chars (e.g., wchar_t) memcpy(destBytes, nativeCharPtr, charCount * sizeof(char)); // Release the byte array back to the JVM (*env)->ReleaseByteArrayElements(env, dest, destBytes, 0); } - Compile the C code into a native library and call the method from Java.
Critical Caveats to Avoid Disaster
- Pointer Validity: Never access a pointer that's been freed, points to memory outside your process, or is uninitialized—this will crash the JVM instantly.
- Character Encoding: C's
charis ambiguous: it can be 1-byte (ASCII/UTF-8) or 2-byte (wide chars). You must know the exact encoding/byte size of the native data to avoid garbage in yourbyte[]. - Byte Order: If working with wide chars, note that native systems often use little-endian byte order, while Java uses big-endian. You may need to swap bytes if the data is UTF-16.
- Memory Management: If you allocated the native
char*yourself, ensure you have a native method to free that memory to avoid leaks. - Unsafe Risks:
Unsafebypasses Java's memory safety guarantees—any mistake here can corrupt memory or crash the JVM. Stick to JNI for production systems.
内容的提问来源于stack exchange,提问作者Monseigneur Artous

