Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,83 @@ public void cleanerCreateMethodIsDefined() {
// path to be hit in normal usage.
Assertions.assertTrue(Platform.cleanerCreateMethodIsDefined());
}

@Test
public void reallocateMemoryGrow() {
long address = Platform.allocateMemory(1024);
try {
for (int i = 0; i < 1024; i++) {
Platform.putByte(null, address + i, (byte) i);
}

address = Platform.reallocateMemory(address, 1024, 2048);
for (int i = 0; i < 1024; i++) {
Assertions.assertEquals((byte) i, Platform.getByte(null, address + i));
}
for (int i = 1024; i < 2048; i++) {
Platform.putByte(null, address + i, (byte) i);
}
for (int i = 1024; i < 2048; i++) {
Assertions.assertEquals((byte) i, Platform.getByte(null, address + i));
}
} finally {
Platform.freeMemory(address);
}
}

@Test
public void reallocateMemoryShrinkDoesNotOverflow() {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current implementation anticipates that this particular case should fail.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least it causes memory corruption in my local macOS tests.

[INFO] Running org.apache.spark.unsafe.PlatformUtilSuite
/bin/sh: line 1: 51900 Abort trap: 6           '/Users/yangjie01/Tools/zulu17/zulu-17.jdk/Contents/Home/bin/java' '-ea' '-Xmx4g' '-Xss4m' '-XX:MaxMetaspaceSize=2g' '-XX:ReservedCodeCacheSize=128m' '-XX:+IgnoreUnrecognizedVMOptions' '--add-modules=jdk.incubator.vector' '--add-opens=java.base/java.lang=ALL-UNNAMED' '--add-opens=java.base/java.lang.invoke=ALL-UNNAMED' '--add-opens=java.base/java.lang.reflect=ALL-UNNAMED' '--add-opens=java.base/java.io=ALL-UNNAMED' '--add-opens=java.base/java.net=ALL-UNNAMED' '--add-opens=java.base/java.nio=ALL-UNNAMED' '--add-opens=java.base/java.util=ALL-UNNAMED' '--add-opens=java.base/java.util.concurrent=ALL-UNNAMED' '--add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED' '--add-opens=java.base/jdk.internal.ref=ALL-UNNAMED' '--add-opens=java.base/sun.nio.ch=ALL-UNNAMED' '--add-opens=java.base/sun.nio.cs=ALL-UNNAMED' '--add-opens=java.base/sun.security.action=ALL-UNNAMED' '--add-opens=java.base/sun.util.calendar=ALL-UNNAMED' '-Djdk.reflect.useDirectMethodHandle=false' '-Dio.netty.tryReflectionSetAccessible=true' '-Dio.netty.allocator.type=pooled' '-Dio.netty.handler.ssl.defaultEndpointVerificationAlgorithm=NONE' '-Dio.netty.noUnsafe=false' '--enable-native-access=ALL-UNNAMED' '-jar' '/Users/yangjie01/SourceCode/git/spark-maven/common/unsafe/target/surefire/surefirebooter-20260227205732081_3.jar' '/Users/yangjie01/SourceCode/git/spark-maven/common/unsafe/target/surefire' '2026-02-27T20-57-32_053-jvmRun1' 'surefire-20260227205732081_1tmp' 'surefire_0-20260227205732081_2tmp'
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 88, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  10.128 s
[INFO] Finished at: 2026-02-27T20:57:34+08:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:3.5.3:test (default-test) on project spark-unsafe_2.13: 
[ERROR] 
[ERROR] See /Users/yangjie01/SourceCode/git/spark-maven/common/unsafe/target/surefire-reports for the individual test results.
[ERROR] See dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream.
[ERROR] The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
[ERROR] Command was /bin/sh -c cd '/Users/yangjie01/SourceCode/git/spark-maven/common/unsafe' && '/Users/yangjie01/Tools/zulu17/zulu-17.jdk/Contents/Home/bin/java' '-ea' '-Xmx4g' '-Xss4m' '-XX:MaxMetaspaceSize=2g' '-XX:ReservedCodeCacheSize=128m' '-XX:+IgnoreUnrecognizedVMOptions' '--add-modules=jdk.incubator.vector' '--add-opens=java.base/java.lang=ALL-UNNAMED' '--add-opens=java.base/java.lang.invoke=ALL-UNNAMED' '--add-opens=java.base/java.lang.reflect=ALL-UNNAMED' '--add-opens=java.base/java.io=ALL-UNNAMED' '--add-opens=java.base/java.net=ALL-UNNAMED' '--add-opens=java.base/java.nio=ALL-UNNAMED' '--add-opens=java.base/java.util=ALL-UNNAMED' '--add-opens=java.base/java.util.concurrent=ALL-UNNAMED' '--add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED' '--add-opens=java.base/jdk.internal.ref=ALL-UNNAMED' '--add-opens=java.base/sun.nio.ch=ALL-UNNAMED' '--add-opens=java.base/sun.nio.cs=ALL-UNNAMED' '--add-opens=java.base/sun.security.action=ALL-UNNAMED' '--add-opens=java.base/sun.util.calendar=ALL-UNNAMED' '-Djdk.reflect.useDirectMethodHandle=false' '-Dio.netty.tryReflectionSetAccessible=true' '-Dio.netty.allocator.type=pooled' '-Dio.netty.handler.ssl.defaultEndpointVerificationAlgorithm=NONE' '-Dio.netty.noUnsafe=false' '--enable-native-access=ALL-UNNAMED' '-jar' '/Users/yangjie01/SourceCode/git/spark-maven/common/unsafe/target/surefire/surefirebooter-20260227205732081_3.jar' '/Users/yangjie01/SourceCode/git/spark-maven/common/unsafe/target/surefire' '2026-02-27T20-57-32_053-jvmRun1' 'surefire-20260227205732081_1tmp' 'surefire_0-20260227205732081_2tmp'
[ERROR] Error occurred in starting fork, check output in log
[ERROR] Process Exit Code: 134
[ERROR] Crashed tests:
[ERROR] org.apache.spark.unsafe.PlatformUtilSuite
[ERROR] org.apache.maven.surefire.booter.SurefireBooterForkException: The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
[ERROR] Command was /bin/sh -c cd '/Users/yangjie01/SourceCode/git/spark-maven/common/unsafe' && '/Users/yangjie01/Tools/zulu17/zulu-17.jdk/Contents/Home/bin/java' '-ea' '-Xmx4g' '-Xss4m' '-XX:MaxMetaspaceSize=2g' '-XX:ReservedCodeCacheSize=128m' '-XX:+IgnoreUnrecognizedVMOptions' '--add-modules=jdk.incubator.vector' '--add-opens=java.base/java.lang=ALL-UNNAMED' '--add-opens=java.base/java.lang.invoke=ALL-UNNAMED' '--add-opens=java.base/java.lang.reflect=ALL-UNNAMED' '--add-opens=java.base/java.io=ALL-UNNAMED' '--add-opens=java.base/java.net=ALL-UNNAMED' '--add-opens=java.base/java.nio=ALL-UNNAMED' '--add-opens=java.base/java.util=ALL-UNNAMED' '--add-opens=java.base/java.util.concurrent=ALL-UNNAMED' '--add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED' '--add-opens=java.base/jdk.internal.ref=ALL-UNNAMED' '--add-opens=java.base/sun.nio.ch=ALL-UNNAMED' '--add-opens=java.base/sun.nio.cs=ALL-UNNAMED' '--add-opens=java.base/sun.security.action=ALL-UNNAMED' '--add-opens=java.base/sun.util.calendar=ALL-UNNAMED' '-Djdk.reflect.useDirectMethodHandle=false' '-Dio.netty.tryReflectionSetAccessible=true' '-Dio.netty.allocator.type=pooled' '-Dio.netty.handler.ssl.defaultEndpointVerificationAlgorithm=NONE' '-Dio.netty.noUnsafe=false' '--enable-native-access=ALL-UNNAMED' '-jar' '/Users/yangjie01/SourceCode/git/spark-maven/common/unsafe/target/surefire/surefirebooter-20260227205732081_3.jar' '/Users/yangjie01/SourceCode/git/spark-maven/common/unsafe/target/surefire' '2026-02-27T20-57-32_053-jvmRun1' 'surefire-20260227205732081_1tmp' 'surefire_0-20260227205732081_2tmp'
[ERROR] Error occurred in starting fork, check output in log
[ERROR] Process Exit Code: 134
[ERROR] Crashed tests:
[ERROR] org.apache.spark.unsafe.PlatformUtilSuite
[ERROR] 	at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:643)
[ERROR] 	at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:285)
[ERROR] 	at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:250)
[ERROR] 	at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1337)
[ERROR] 	at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:1135)
[ERROR] 	at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:969)
[ERROR] 	at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:126)
[ERROR] 	at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2(MojoExecutor.java:328)
[ERROR] 	at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute(MojoExecutor.java:316)
[ERROR] 	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:212)
[ERROR] 	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:174)
[ERROR] 	at org.apache.maven.lifecycle.internal.MojoExecutor.access$000(MojoExecutor.java:75)
[ERROR] 	at org.apache.maven.lifecycle.internal.MojoExecutor$1.run(MojoExecutor.java:162)
[ERROR] 	at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute(DefaultMojosExecutionStrategy.java:39)
[ERROR] 	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:159)
[ERROR] 	at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:105)
[ERROR] 	at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:73)
[ERROR] 	at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:53)
[ERROR] 	at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:118)
[ERROR] 	at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:261)
[ERROR] 	at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:173)
[ERROR] 	at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:101)
[ERROR] 	at org.apache.maven.cli.MavenCli.execute(MavenCli.java:919)
[ERROR] 	at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:285)
[ERROR] 	at org.apache.maven.cli.MavenCli.main(MavenCli.java:207)
[ERROR] 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR] 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
[ERROR] 	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR] 	at java.base/java.lang.reflect.Method.invoke(Method.java:569)
[ERROR] 	at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:255)
[ERROR] 	at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:201)
[ERROR] 	at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:361)
[ERROR] 	at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:314)
[ERROR] 
[ERROR] -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

long oldSize = 1024L;
long newSize = 512L;
long sentinelSize = oldSize - newSize;
byte sentinelValue = (byte) 0xAB;
byte sourceValue = (byte) 0xCD;
int pairs = 1000;

long[] sources = new long[pairs];
long[] sentinels = new long[pairs];

try {
// Allocate all pairs
for (int i = 0; i < pairs; i++) {
sources[i] = Platform.allocateMemory(oldSize);
sentinels[i] = Platform.allocateMemory(sentinelSize);

Platform.setMemory(sources[i], sourceValue, oldSize);
Platform.setMemory(sentinels[i], sentinelValue, sentinelSize);
}

// Reallocate source blocks
for (int i = 0; i < pairs; i++) {
long oldAddr = sources[i];
long newAddr = Platform.reallocateMemory(oldAddr, oldSize, newSize);
sources[i] = newAddr;
}

// Verify dest content
for (int i = 0; i < pairs; i++) {
for (long j = 0; j < newSize; j++) {
Assertions.assertEquals(sourceValue, Platform.getByte(null, sources[i] + j),
"dest block content corrupted at pair " + i);
}
}

// Verify sentinel content
for (int i = 0; i < pairs; i++) {
for (long j = 0; j < sentinelSize; j++) {
Assertions.assertEquals(sentinelValue, Platform.getByte(null, sentinels[i] + j),
"sentinel corrupted – overflow write detected at pair " + i);
}
}

} finally {
// Free all memory
for (long addr : sources) {
if (addr != 0) Platform.freeMemory(addr);
}
for (long addr : sentinels) {
if (addr != 0) Platform.freeMemory(addr);
}
}
}
}