Javet icon indicating copy to clipboard operation
Javet copied to clipboard

does Javet support graalvm 's native-image ?

Open grdk37 opened this issue 2 years ago • 8 comments

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

grdk37 avatar Jul 24 '23 08:07 grdk37

There's a trick to be played to enable the native image. Please refer to #107 for detail.

caoccao avatar Jul 24 '23 13:07 caoccao

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)

grdk37 avatar Jul 24 '23 15:07 grdk37

Please read the doc carefully. It's a path to where the .dylib file is stored, not the path of that .dylib file.

caoccao avatar Jul 25 '23 05:07 caoccao

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)

grdk37 avatar Jul 25 '23 08:07 grdk37

It seems that Javet doesn't load the binary successfully. Here are something you could do to troubleshoot this:

  1. Use absolute path instead of the relative path.
  2. Adjust the log level to get more log.
  3. Implement your own listener to take over the lib loading phase.
  4. Join the discord to discuss with me in real-time.

Good luck!

caoccao avatar Jul 26 '23 13:07 caoccao

thanks a lot for reply .

i have tried absolute path instead of the relative path, not working now it seems that ,

  1. 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"
  2. 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 ~

grdk37 avatar Jul 27 '23 09:07 grdk37

The lib loading leverages reflection. I'm not sure if you took care of that in your build.

caoccao avatar Jul 27 '23 09:07 caoccao

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 
image image

grdk37 avatar Jul 27 '23 10:07 grdk37