substrate
substrate copied to clipboard
java.lang.NoSuchFieldError: java.net.Inet6Address.cached_scope_id on Android
I have a complex Gluon Mobile application I can't share that I was previously building with Gluon GraalVM 21.2. It uses Socket.IO to connect to another application. Under Gluon GraalVM 22.0 it fails to create the socket.
This application was created using the Gluon Mobile Eclipse plugin (single view project). The versions of the various dependencies and plugins have been updated to their latest versions. The socket creation occurs in GluonApplication
's constructor.
A reproducer is available at: https://github.com/marinier/androidsockettest
Expected Behavior
No exceptions.
Current Behavior
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): Exception in thread "OkHttp Dispatcher" java.lang.NoSuchFieldError: java.net.Inet6Address.cached_scope_id
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at com.oracle.svm.jni.functions.JNIFunctions$Support.getFieldID(JNIFunctions.java:1207)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at com.oracle.svm.jni.functions.JNIFunctions.GetFieldID(JNIFunctions.java:434)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at java.net.Inet6Address.init(Inet6Address.java)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at java.net.Inet6Address.<clinit>(Inet6Address.java:369)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at java.lang.Class.ensureInitialized(DynamicHub.java:510)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at com.oracle.svm.jni.functions.JNIFunctions.FindClass(JNIFunctions.java:355)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at java.net.PlainSocketImpl.initProto(PlainSocketImpl.java)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at java.net.PlainSocketImpl.<clinit>(PlainSocketImpl.java:43)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at java.lang.Class.ensureInitialized(DynamicHub.java:510)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at java.net.Socket.setImpl(Socket.java:523)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at java.net.Socket.<init>(Socket.java:88)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at javax.net.DefaultSocketFactory.createSocket(SocketFactory.java:265)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.java:241)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:167)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:258)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:127)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:257)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at okhttp3.RealCall$AsyncCall.execute(RealCall.java:201)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at java.lang.Thread.run(Thread.java:829)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:597)
[Mon. Feb. 14 12:25:32 EST 2022][INFO] [SUB] D/GraalCompiled( 7241): at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:194)
Steps to Reproduce
Reproducer at: https://github.com/marinier/androidsockettest Using Gluon GraalVM 22.0.0.3 JDK 11:
mvn -Pandroid gluonfx:build gluonfx:package gluonfx:install gluonfx:nativerun
Since this looks like it could be reflection related, I added this to the reflection-config.json:
{
"name":"java.net.Inet6Address",
"allDeclaredConstructors" : true,
"allPublicConstructors" : true,
"allDeclaredMethods" : true,
"allPublicMethods" : true,
"allDeclaredClasses" : true,
"allPublicClasses" : true,
"queryAllPublicConstructors":true
}
But that makes no difference. (The rest of the reflection config was generated using the native agent.)
Your Environment
- Ubuntu 20.04 in a VirtualBox VM on Windows 10
- Gluon GraalVM 22.0.0.3 JDK 11
- Android 12 (although the original application demonstrated the issue on Android 10 as well, I only have access to an Android 10 phone for testing the reproducer)
Error message mentions JNI, did you try adding it to the jni-config.json instead?
For your info, we removed it from the default generated file jni-config.json: https://github.com/gluonhq/substrate/commit/06a0f1431397eebeabc5bdb626654fc8ae70645b
I tried putting the same block I had in the reflection config in the jni config:
{
"name":"java.net.Inet6Address",
"allDeclaredConstructors" : true,
"allPublicConstructors" : true,
"allDeclaredMethods" : true,
"allPublicMethods" : true,
"allDeclaredClasses" : true,
"allPublicClasses" : true,
"queryAllPublicConstructors":true
}
This did not work (same exception). I then tried putting in the configuration from before the change in 06a0f1431397eebeabc5bdb626654fc8ae70645b:
{
"name":"java.net.Inet6Address",
"methods":[{"name":"<init>","parameterTypes":[] }],
"fields":[
{"name":"cached_scope_id"},
{"name":"holder6"}
]
}
But that didn't work either (same exception).
Hmm, so adding the method doesn't work, because it was removed from JDK 11.0.14 (the one used to build Gluon's GraalVM 22.0.0.3), but your dependencies might be still somehow calling it.
For a quick test you could try Gluon's GraalVM 22.0.0.2 that was built with JDK 11.0.13 (which uses that cached_scope_id
field)?
I confirmed that things work with 22.0.0.2 with no additional configuration needed in either reflection config or jni config in both the reproducer and my original app. Thank you!
The socket.io dependencies I'm using for network communication do not mention cached_scope_id
anywhere in their code.
From the exception callstack, this involves the java.net.Inet6Address.init
method, which is native. In the native code it is still trying to use cached_scope_id
.
It seems like this change was intended to deal with the possible absence of this field, but the native java.net.Inet6Address.init
method is still trying to access it. Is it possible this is a bug in the JDK itself? It looks like that native code hasn't been updated since 2017.
This issue might be then with the JDK you are using (is it AdoptOpenJDK?).
GraalVM is built with labsjdk JDK 11.0.13 (for 22.0.0.2) or 11.0.14 (for 22.0.0.3), and labsjdk is forked from OpenJDK/jdk11u itself.
The change was a backport from https://bugs.openjdk.java.net/browse/JDK-8216417 into JDK 11.0.14, and that's why GraalVM has the change registering the field cached_scope_id
based on a given version that you have linked.
See https://github.com/openjdk/jdk11u-dev/blob/master/src/java.base/share/native/libnet/Inet6Address.c, it doesn't have the field. It might be possible that AdoptOpenJDK doesn't include this backport yet?
If you run with export JAVA_HOME=$GRAALVM_HOME
(instead of using Adopt
Sorry, I just linked to open jdk because that's what I found first, and I assumed they were all the same. I checked and the default java on Ubuntu 20.04 is 11.0.13, so I just set JAVA_HOME to GRAALVM_HOME like you said.
soartech@soartech-VirtualBox:~/isaac/isaac$ echo $JAVA_HOME
/home/soartech/graalvm-svm-java11-linux-gluon-22.0.0.3-Final
soartech@soartech-VirtualBox:~/isaac/isaac$ java -version
openjdk version "11.0.14" 2022-01-18
OpenJDK Runtime Environment GraalVM 22.0.0.2 (build 11.0.14+9-jvmci-22.0-b05)
OpenJDK 64-Bit Server VM GraalVM 22.0.0.2 (build 11.0.14+9-jvmci-22.0-b05, mixed mode, sharing)
Unfortunately, I get the same exception.
Have you tried the reproducer I created? https://github.com/marinier/androidsockettest
If it works for you, then we know it's something about my setup (although I don't see what it could be) vs. something in graalvm or substrate or something else.
There is a similar issue reported here: https://github.com/gluonhq/gluonfx-maven-plugin/issues/417
I've tested your project with GraalVM 22.0.0.3 (JDK11), on Android 10,
Either with an old OpenJDK 11.0.2 or when doing export JAVA_HOME=$GRAALVM_HOME
, I get
[Fri Feb 18 23:47:34 CET 2022][INFO] [SUB] D/GraalCompiled(11789): Exception in thread "OkHttp Dispatcher" java.lang.NoSuchFieldError: java.net.Inet6Address.cached_scope_id
[Fri Feb 18 23:47:34 CET 2022][INFO] [SUB] D/GraalCompiled(11789): at com.oracle.svm.jni.functions.JNIFunctions$Support.getFieldID(JNIFunctions.java:1207)
[Fri Feb 18 23:47:34 CET 2022][INFO] [SUB] D/GraalCompiled(11789): at com.oracle.svm.jni.functions.JNIFunctions.GetFieldID(JNIFunctions.java:434)
[Fri Feb 18 23:47:34 CET 2022][INFO] [SUB] D/GraalCompiled(11789): at java.net.Inet6Address.init(Inet6Address.java)
[Fri Feb 18 23:47:34 CET 2022][INFO] [SUB] D/GraalCompiled(11789): at java.net.Inet6Address.<clinit>(Inet6Address.java:369)
[Fri Feb 18 23:47:34 CET 2022][INFO] [SUB] D/GraalCompiled(11789): at java.lang.Class.ensureInitialized(DynamicHub.java:510)
Building with 22.0.0.3 (JDK17) works fine though. No exception is shown.
I might have an explanation for this issue: Substrate for Android uses java static libs from openjdk/mobile, for JDK 17 the libs were recently generated, but for 11 these libs use an old version: https://github.com/gluonhq/substrate/blob/master/src/main/java/com/gluonhq/substrate/Constants.java#L109
that was done before the inet6Address change was done. Therefore, there is a mismatch between GraalVM and Substrate Java/static.
The proper fix will be building again the Java/static libs for mobile with the latest JDK 11 (right, @johanvos ?).
For what it's worth, I've just upgraded
From:
- <maven.compiler.release>11</maven.compiler.release>
- <gluonfx.plugin.version>1.0.12</gluonfx.plugin.version>
- <charm-glisten.version>6.1.1</charm-glisten.version>
- <gluonhq-attach.version>4.0.14</gluonhq-attach.version>
- GRAALVM_HOME=/opt/graalvm/graalvm-svm-java11-linux-gluon-22.0.0.3-Final
To:
- <maven.compiler.release>17</maven.compiler.release>
- <gluonfx.plugin.version>1.0.16</gluonfx.plugin.version>
- <charm-glisten.version>6.2.2</charm-glisten.version>
- <gluonhq-attach.version>4.0.16</gluonhq-attach.version>
- GRAALVM_HOME=/opt/graalvm/graalvm-svm-java17-linux-gluon-22.1.0.1-Final
and all of my build / run problems went away.
Note, I still had some dwindling issues afterwards which cleared up after I purged folder ~/.gluon/substrate/Android and updated file src/android/AndroidManifest.xml with new, required attribute android:exported="true".