does Javet support graalvm 's native-image ?
one java class which used Javet can be compiled to. native-image ?
about native-image https://www.graalvm.org/22.3/reference-manual/native-image/#build-a-native-executable i have test one class in my macos,but failed
javac -cp ".:javet-macos-2.2.1.jar" js/TestJavet.java
java -cp ".:javet-macos-2.2.1.jar" -agentlib:native-image-agent=config-output-dir=config js.TestJavet
native-image --no-fallback --verbose -H:ConfigurationFileDirectories=config -cp ".:javet-macos-2.2.1.jar" js.TestJavet
Finished generating 'js.testjavet' in 1m 23s. i success generate the js.testjavet file ,but when i try to execute the file .
i get this
bogon:java jamie$ ./js.testjavet
com.oracle.svm.core.jdk.UnsupportedFeatureError: No classes have been predefined during the image build to load from bytecodes at runtime.
at org.graalvm.nativeimage.builder/com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:89)
at org.graalvm.nativeimage.builder/com.oracle.svm.core.hub.PredefinedClassesSupport.throwNoBytecodeClasses(PredefinedClassesSupport.java:76)
at org.graalvm.nativeimage.builder/com.oracle.svm.core.hub.PredefinedClassesSupport.loadClass(PredefinedClassesSupport.java:130)
at [email protected]/java.lang.ClassLoader.defineClass(ClassLoader.java:288)
at com.caoccao.javet.interop.JavetClassLoader.loadClass(JavetClassLoader.java:110)
at com.caoccao.javet.interop.JavetClassLoader.load(JavetClassLoader.java:83)
at com.caoccao.javet.interop.V8Host.loadLibrary(V8Host.java:418)
at com.caoccao.javet.interop.V8Host.<init>(V8Host.java:67)
at com.caoccao.javet.interop.V8Host.<init>(V8Host.java:43)
at com.caoccao.javet.interop.V8Host$V8InstanceHolder.<clinit>(V8Host.java:459)
at com.caoccao.javet.interop.V8Host.getV8Instance(V8Host.java:119)
at js.TestJavet.test(TestJavet.java:68)
at js.TestJavet.main(TestJavet.java:25)
java.lang.ClassNotFoundException: com.caoccao.javet.interop.loader.JavetLibLoader
at com.caoccao.javet.interop.JavetClassLoader.loadClass(JavetClassLoader.java:116)
at com.caoccao.javet.interop.JavetClassLoader.load(JavetClassLoader.java:83)
at com.caoccao.javet.interop.V8Host.loadLibrary(V8Host.java:418)
at com.caoccao.javet.interop.V8Host.<init>(V8Host.java:67)
at com.caoccao.javet.interop.V8Host.<init>(V8Host.java:43)
at com.caoccao.javet.interop.V8Host$V8InstanceHolder.<clinit>(V8Host.java:459)
at com.caoccao.javet.interop.V8Host.getV8Instance(V8Host.java:119)
at js.TestJavet.test(TestJavet.java:68)
at js.TestJavet.main(TestJavet.java:25)
Caused by: com.oracle.svm.core.jdk.UnsupportedFeatureError: No classes have been predefined during the image build to load from bytecodes at runtime.
at org.graalvm.nativeimage.builder/com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:89)
at org.graalvm.nativeimage.builder/com.oracle.svm.core.hub.PredefinedClassesSupport.throwNoBytecodeClasses(PredefinedClassesSupport.java:76)
at org.graalvm.nativeimage.builder/com.oracle.svm.core.hub.PredefinedClassesSupport.loadClass(PredefinedClassesSupport.java:130)
at [email protected]/java.lang.ClassLoader.defineClass(ClassLoader.java:288)
at com.caoccao.javet.interop.JavetClassLoader.loadClass(JavetClassLoader.java:110)
... 8 more
7月 24, 2023 4:46:33 下午 com.caoccao.javet.utils.JavetDefaultLogger error
严重: Failed to load Javet lib with error Javet library is not loaded because com.caoccao.javet.interop.loader.JavetLibLoader.
7月 24, 2023 4:46:33 下午 com.caoccao.javet.utils.JavetDefaultLogger error
严重: com.caoccao.javet.exceptions.JavetException: Javet library is not loaded because com.caoccao.javet.interop.loader.JavetLibLoader
at com.caoccao.javet.interop.JavetClassLoader.load(JavetClassLoader.java:93)
at com.caoccao.javet.interop.V8Host.loadLibrary(V8Host.java:418)
at com.caoccao.javet.interop.V8Host.<init>(V8Host.java:67)
at com.caoccao.javet.interop.V8Host.<init>(V8Host.java:43)
at com.caoccao.javet.interop.V8Host$V8InstanceHolder.<clinit>(V8Host.java:459)
at com.caoccao.javet.interop.V8Host.getV8Instance(V8Host.java:119)
at js.TestJavet.test(TestJavet.java:68)
at js.TestJavet.main(TestJavet.java:25)
Caused by: java.lang.ClassNotFoundException: com.caoccao.javet.interop.loader.JavetLibLoader
at com.caoccao.javet.interop.JavetClassLoader.loadClass(JavetClassLoader.java:116)
at com.caoccao.javet.interop.JavetClassLoader.load(JavetClassLoader.java:83)
... 7 more
Caused by: com.oracle.svm.core.jdk.UnsupportedFeatureError: No classes have been predefined during the image build to load from bytecodes at runtime.
at org.graalvm.nativeimage.builder/com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:89)
at org.graalvm.nativeimage.builder/com.oracle.svm.core.hub.PredefinedClassesSupport.throwNoBytecodeClasses(PredefinedClassesSupport.java:76)
at org.graalvm.nativeimage.builder/com.oracle.svm.core.hub.PredefinedClassesSupport.loadClass(PredefinedClassesSupport.java:130)
at [email protected]/java.lang.ClassLoader.defineClass(ClassLoader.java:288)
at com.caoccao.javet.interop.JavetClassLoader.loadClass(JavetClassLoader.java:110)
... 8 more
Exception in thread "main" com.caoccao.javet.exceptions.JavetException: Javet library is not loaded because com.caoccao.javet.interop.loader.JavetLibLoader
at com.caoccao.javet.interop.JavetClassLoader.load(JavetClassLoader.java:93)
at com.caoccao.javet.interop.V8Host.loadLibrary(V8Host.java:418)
at com.caoccao.javet.interop.V8Host.<init>(V8Host.java:67)
at com.caoccao.javet.interop.V8Host.<init>(V8Host.java:43)
at com.caoccao.javet.interop.V8Host$V8InstanceHolder.<clinit>(V8Host.java:459)
at com.caoccao.javet.interop.V8Host.getV8Instance(V8Host.java:119)
at js.TestJavet.test(TestJavet.java:68)
at js.TestJavet.main(TestJavet.java:25)
Caused by: java.lang.ClassNotFoundException: com.caoccao.javet.interop.loader.JavetLibLoader
at com.caoccao.javet.interop.JavetClassLoader.loadClass(JavetClassLoader.java:116)
at com.caoccao.javet.interop.JavetClassLoader.load(JavetClassLoader.java:83)
... 7 more
Caused by: com.oracle.svm.core.jdk.UnsupportedFeatureError: No classes have been predefined during the image build to load from bytecodes at runtime.
at org.graalvm.nativeimage.builder/com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:89)
at org.graalvm.nativeimage.builder/com.oracle.svm.core.hub.PredefinedClassesSupport.throwNoBytecodeClasses(PredefinedClassesSupport.java:76)
at org.graalvm.nativeimage.builder/com.oracle.svm.core.hub.PredefinedClassesSupport.loadClass(PredefinedClassesSupport.java:130)
at [email protected]/java.lang.ClassLoader.defineClass(ClassLoader.java:288)
at com.caoccao.javet.interop.JavetClassLoader.loadClass(JavetClassLoader.java:110)
... 8 more
There's a trick to be played to enable the native image. Please refer to #107 for detail.
sorry ,i still donot know how to make it through graalvm . could you please explain it in detail ,thank you so much .
javac -cp ".:javet-macos-2.2.1.jar" js/TestJavet.java
java -cp ".:javet-macos-2.2.1.jar" -agentlib:native-image-agent=config-output-dir=config,experimental-class-define-support js.TestJavet
native-image -Djavet.lib.loading.path=./libjavet-v8-macos-x86_64.v.2.2.1.dylib -Djavet.lib.loading.type=custom -cp ".:javet-macos-2.2.1.jar" --no-fallback --verbose -H:ConfigurationFileDirectories=config js.TestJavet
still not work
try (V8Runtime v8Runtime = V8Host.getV8Instance().createV8Runtime())
my macos is x86_64 , not arm cpu
using graalvm Version info: 'GraalVM 22.3.2 Java 17 EE' Java version info: '17.0.7+8-LTS-jvmci-22.3-b15' C compiler: cc (apple, x86_64, 14.0.0)
Please read the doc carefully. It's a path to where the .dylib file is stored, not the path of that .dylib file.
after some hours working ,now the class "com.caoccao.javet.interop.loader.JavetLibLoader" can be loaded . give the credit to "--initialize-at-build-time" . but another error shows up as below
# check the grallvm version
bogon:java jamie$ java -version
openjdk version "17.0.7" 2023-04-18
OpenJDK Runtime Environment GraalVM CE 17.0.7+7.1 (build 17.0.7+7-jvmci-23.0-b12)
OpenJDK 64-Bit Server VM GraalVM CE 17.0.7+7.1 (build 17.0.7+7-jvmci-23.0-b12, mixed mode, sharing)
#extract the jar ,so it will not need the "-cp" option any more
tar -xzf javet-macos-2.2.1.jar
# compile
javac js/TestJavet.java
# test for running ,it can running well.
java js.TestJavet
# remove former config path and generates new
rm -rf config
java -agentlib:native-image-agent=config-output-dir=config js.TestJavet
# put the libjavet-v8-macos-x86_64.v.2.2.1.dylib in current directory and generate native-image , it will succeed ,
native-image -Djavet.lib.loading.path="./" -Djavet.lib.loading.type=custom --initialize-at-build-time --no-fallback --verbose js.TestJavet
# run it
bogon:java jamie$ ./js.testjavet
1111
Exception in thread "main" java.lang.UnsatisfiedLinkError: com.caoccao.javet.interop.V8Native.createV8Runtime(Ljava/lang/Object;)J [symbol: Java_com_caoccao_javet_interop_V8Native_createV8Runtime or Java_com_caoccao_javet_interop_V8Native_createV8Runtime__Ljava_lang_Object_2]
at org.graalvm.nativeimage.builder/com.oracle.svm.core.jni.access.JNINativeLinkage.getOrFindEntryPoint(JNINativeLinkage.java:152)
at org.graalvm.nativeimage.builder/com.oracle.svm.core.jni.JNIGeneratedMethodSupport.nativeCallAddress(JNIGeneratedMethodSupport.java:53)
at com.caoccao.javet.interop.V8Native.createV8Runtime(Native Method)
at com.caoccao.javet.interop.V8Host.createV8Runtime(V8Host.java:265)
at com.caoccao.javet.interop.V8Host.createV8Runtime(V8Host.java:240)
at com.caoccao.javet.interop.V8Host.createV8Runtime(V8Host.java:227)
at js.TestJavet.test(TestJavet.java:75)
at js.TestJavet.main(TestJavet.java:25)
It seems that Javet doesn't load the binary successfully. Here are something you could do to troubleshoot this:
- Use absolute path instead of the relative path.
- Adjust the log level to get more log.
- Implement your own listener to take over the lib loading phase.
- Join the discord to discuss with me in real-time.
Good luck!
thanks a lot for reply .
i have tried absolute path instead of the relative path, not working now it seems that ,
- if donot use. " --initialize-at-build-time " , when running the native image , cannot find "com.caoccao.javet.interop.loader.JavetLibLoader" class, even if using " java -agentlib:native-image-agent=config-output-dir=config,experimental-class-define-support js.TestJavet"
- if using --initialize-at-build-time , when running the native image , the class was initialed at build time, so at run time canot find the class . and. a java.lang.UnsatisfiedLinkError. pops up
if the respected Author have enough time in future , would you please add the detailed steps about building a native image in one platform (linux,macos,windows) to the tutorial doc . i believe one platform may be enough , the other platform will be similar.
maybe graalvm will be more and more important in future, so add this part to the document will be useful.
thank you so much ~
The lib loading leverages reflection. I'm not sure if you took care of that in your build.
it seems that "com.oracle.svm.core.jdk.UnsupportedFeatureError: No classes have been predefined during the image build to load from bytecodes at runtime." occurs on com.caoccao.javet.interop.JavetClassLoader 118 lines
Class<?> classJavetLibLoader = defineClass(name, buffer, 0, buffer.length);
to find the reason of the problem , i changed the. JavetClassLoader class a little .
the command to generate native image
tar -xzf javet-macos-2.2.1.jar
javac js/TestJavet.java
java -agentlib:native-image-agent=config-output-dir=config,experimental-class-define-support js.TestJavet
native-image -Djavet.lib.loading.path="/Users/jamie/data/js" -Djavet.lib.loading.type=custom --link-at-build-time \
-- verbose -H:ConfigurationFileDirectories=config -H:+ReportExceptionStackTraces js.TestJavet
./js.testjavet