From 09880a94463c0b1936bf19c3a5b42eea9551c0df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillermo=20Rodr=C3=ADguez?= Date: Sun, 23 Aug 2026 20:00:52 +0200 Subject: [PATCH] OpenJDK: Implement JVM_CopySwapMemory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenJDK 8u201 added JVM_CopySwapMemory (as part of the OpenJDK 8 backport of JDK-8141491), which copies memory between two regions while swapping the byte order of each element. Without it, the process crashes on the first bulk NIO transfer involving a byte-swapped buffer. The implementation uses a simple byte-reversal loop with byte-wise reads and writes, allowing unaligned source and destination addresses. The copy is overlap-safe: When the ranges overlap, copying proceeds in a direction that prevents unread source bytes from being overwritten. Signed-off-by: Guillermo Rodríguez --- src/classlib/openjdk/jvm.c | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/classlib/openjdk/jvm.c b/src/classlib/openjdk/jvm.c index 0f63fa6..a1d45c5 100644 --- a/src/classlib/openjdk/jvm.c +++ b/src/classlib/openjdk/jvm.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2010, 2011, 2012, 2013, 2014 * Robert Lougher . + * Copyright (C) 2026 INGELABS S.L. . * * This file is part of JamVM. * @@ -3082,3 +3083,42 @@ jstring JVM_GetTemporaryDirectory(JNIEnv *env) { */ return createString("/tmp"); } + +/* JVM_CopySwapMemory */ + +void JVM_CopySwapMemory(JNIEnv *env, jobject srcObj, jlong srcOffset, + jobject dstObj, jlong dstOffset, jlong size, + jlong elemSize) { + + char *src = srcObj == NULL ? (char *)(uintptr_t)srcOffset + : (char *)srcObj + srcOffset; + char *dst = dstObj == NULL ? (char *)(uintptr_t)dstOffset + : (char *)dstObj + dstOffset; + jlong i, j; + + TRACE("JVM_CopySwapMemory(env=%p, srcObj=%p, srcOffset=%lld, " + "dstObj=%p, dstOffset=%lld, size=%lld, elemSize=%lld)", + env, srcObj, srcOffset, dstObj, dstOffset, size, elemSize); + + /* The ranges may overlap. Copy forward when the destination begins + at or before the source; otherwise copy backward, which is also safe + when the ranges do not overlap. */ + + if((uintptr_t)dst <= (uintptr_t)src) { + char tmp[8]; + for(i = 0; i < size; i += elemSize) { + for(j = 0; j < elemSize; j++) + tmp[j] = src[i + j]; + for(j = 0; j < elemSize; j++) + dst[i + j] = tmp[elemSize - 1 - j]; + } + } else { + char tmp[8]; + for(i = size - elemSize; i >= 0; i -= elemSize) { + for(j = 0; j < elemSize; j++) + tmp[j] = src[i + j]; + for(j = 0; j < elemSize; j++) + dst[i + j] = tmp[elemSize - 1 - j]; + } + } +}