Skip to content

Instantly share code, notes, and snippets.

@raphw
Last active February 18, 2024 08:48
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save raphw/e0f6864ddcad69630d839c2eebaad818 to your computer and use it in GitHub Desktop.
Save raphw/e0f6864ddcad69630d839c2eebaad818 to your computer and use it in GitHub Desktop.
Runs Mockito on Graal VM
#!/bin/bash
set -x
set -e
if [[ -z $1 ]]; then
echo "Specify location of Graal VM as first argument"
exit 1
fi
$1/bin/gu install native-image
rm -rf META-INF sample sample.build_artifacts.txt Sample.* *.jar
echo "public class Sample {
public static void main(String[] args) {
Sample sample = org.mockito.Mockito.mock(Sample.class);
org.mockito.Mockito.when(sample.m()).thenReturn(\"Hello Graal!\");
System.out.println(sample.getClass());
System.out.println(sample.m());
}
public String m() { return null; }
}" > Sample.java
wget -O bytebuddy.jar https://search.maven.org/remotecontent?filepath=net/bytebuddy/byte-buddy/1.12.10/byte-buddy-1.12.10.jar
wget -O mockito.jar https://search.maven.org/remotecontent?filepath=org/mockito/mockito-core/4.5.0/mockito-core-4.5.0.jar
wget -O objenesis.jar https://search.maven.org/remotecontent?filepath=org/objenesis/objenesis/3.2/objenesis-3.2.jar
export dependencies=bytebuddy.jar:mockito.jar:objenesis.jar:.
$1/bin/javac -cp $dependencies Sample.java
$1/bin/java -agentlib:native-image-agent=config-output-dir=META-INF/native-image,experimental-class-define-support -cp $dependencies Sample
$1/bin/native-image --no-fallback -cp $dependencies \
--rerun-class-initialization-at-runtime=\
net.bytebuddy.ClassFileVersion,\
net.bytebuddy.utility.dispatcher.JavaDispatcher,\
net.bytebuddy.utility.Invoker\$Dispatcher \
--initialize-at-build-time=\
net.bytebuddy.description.method.MethodDescription\$InDefinedShape\$AbstractBase\$ForLoadedExecutable,\
net.bytebuddy.description.type.TypeDescription\$AbstractBase,\
net.bytebuddy.description.type.TypeDescription\$ForLoadedType,\
net.bytebuddy.description.method.MethodDescription\$ForLoadedMethod,\
net.bytebuddy.implementation.bind.annotation.Argument\$BindingMechanic,\
net.bytebuddy.implementation.bind.annotation.Argument\$BindingMechanic\$1,\
net.bytebuddy.implementation.bind.annotation.Argument\$BindingMechanic\$2,\
net.bytebuddy.implementation.bind.annotation.Super\$Instantiation\$2 \
Sample
./sample
@phejl
Copy link

phejl commented Jan 7, 2023

@raphw May I suggest update? Replacing --rerun-class-initialization-at-runtime with -H:ClassInitialization (and adding net.bytebuddy.utility.GraalImageCode:rerun). Only after that the sample works with recent GraalVM.

...
-H:ClassInitialization=\
net.bytebuddy.ClassFileVersion:rerun,\
net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun,\
net.bytebuddy.utility.Invoker\$Dispatcher:rerun,\
net.bytebuddy.utility.GraalImageCode:rerun \
...

@linghengqian
Copy link

  • For Graalvm CE 22.3, there is the following warning.
Warning: Using a deprecated option --rerun-class-initialization-at-runtime from command line. Currently there is no replacement for this option. Try using --initialize-at-run-time or use the non-API option -H:ClassInitialization directly.
Warning: Using a deprecated option --rerun-class-initialization-at-runtime from command line. Currently there is no replacement for this option. Try using --initialize-at-run-time or use the non-API option -H:ClassInitialization directly.
Warning: Using a deprecated option --rerun-class-initialization-at-runtime from command line. Currently there is no replacement for this option. Try using --initialize-at-run-time or use the non-API option -H:ClassInitialization directly.

@linghengqian
Copy link

linghengqian commented Jan 21, 2023

  • @phejl Grateful. So for GraalVM Native Build Tools 0.9.19, I did the following in build.gradle. It looks like net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader is important.
plugins {
    id 'java'
    id 'org.graalvm.buildtools.native' version '0.9.19'
}

group 'com.lingh'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.2'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.2'
    testImplementation 'org.apache.shardingsphere.elasticjob:elasticjob-lite-core:3.0.2'
    testImplementation 'org.mockito:mockito-inline:4.11.0'
    testImplementation 'org.mockito:mockito-junit-jupiter:4.11.0'
    testImplementation 'org.hamcrest:hamcrest:2.2'
    testImplementation 'org.awaitility:awaitility:4.2.0'
    testImplementation 'ch.qos.logback:logback-classic:1.2.11'
}

test {
    useJUnitPlatform()
}

graalvmNative {
    binaries {
        test {
           buildArgs.add('-H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun')
            buildArgs.add('-H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun')
            buildArgs.add('-H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun')
            buildArgs.add('-H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun')
            buildArgs.add('--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable')
            buildArgs.add('--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase')
            buildArgs.add('--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType')
            buildArgs.add('--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod')
            buildArgs.add('--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic')
            buildArgs.add('--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1')
            buildArgs.add('--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2')
            buildArgs.add('--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2')
            buildArgs.add('--initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader')
        }
    }
    agent {
        defaultMode = "standard"
        modes {
            conditional {
                userCodeFilterPath = "user-code-filter.json"
            }
        }
        metadataCopy {
            mergeWithExisting = true
            inputTaskNames.add("test")
            outputDirectories.add("src/test/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/elasticjob-lite-core")
        }
        enableExperimentalPredefinedClasses = true
    }
    metadataRepository {
        enabled = true
    }
}

@phejl
Copy link

phejl commented Jan 21, 2023

@linghengqian Nice. Yes for newer libs there is also that DynamicCLassLoader. BTW are you sure about those \\$ escapings? They were important in the shell script, I don't think you need them in your Strings in Groovy. My 2 cents.

@linghengqian
Copy link

linghengqian commented Jan 21, 2023

@linghengqian Nice. Yes for newer libs there is also that DynamicCLassLoader. BTW are you sure about those \\$ escapings? They were important in the shell script, I don't think you need them in your Strings in Groovy. My 2 cents.

- The escape character is automatically added by the IDE when copying and pasting. It seems that only in this way, the build Log of NativeTest is normal.

@linghengqian
Copy link

linghengqian commented Feb 3, 2023

@linghengqian Nice. Yes for newer libs there is also that DynamicCLassLoader. BTW are you sure about those \\$ escapings? They were important in the shell script, I don't think you need them in your Strings in Groovy. My 2 cents.

  • @phejl I noticed an issue with my comment earlier while working on apache/shardingsphere#21347, I just updated my comment above. You are correct, I misunderstood something earlier due to Gradle Cache.

  • And due to issues on the Junit 5 Platform side, not all mockito-inline 4.11 use cases pass nativeTest properly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment