Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

graalvm java native image fails due to randomness in loading the proxies #223

Closed
ganeshs4 opened this issue May 26, 2022 · 2 comments
Closed

Comments

@ganeshs4
Copy link

ganeshs4 commented May 26, 2022

I have been trying to generate java native image (graalvm) for my home automation project which uses pi4j library (it's an amazing library for raspberry pi!).

The native-image is created without any issues. However, when trying to run the native-image, I ran into below issue:

Exception in thread "main" com.oracle.svm.core.jdk.UnsupportedFeatureError: Proxy class defined by interfaces [interface com.pi4j.common.Identity, interface com.pi4j.common.Lifecycle, interface com.pi4j.plugin.raspberrypi.provider.spi.RpiSpiProvider, interface com.pi4j.common.Describable, interface com.pi4j.extension.Extension, interface com.pi4j.io.spi.SpiProvider, interface com.pi4j.provider.Provider] not found. Generating proxy classes at runtime is not supported. Proxy classes need to be defined at image build time by specifying the list of interfaces that they implement. To define proxy classes use -H:DynamicProxyConfigurationFiles=<comma-separated-config-files> and -H:DynamicProxyConfigurationResources=<comma-separated-config-resources> options.
	at com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:89)
	at com.oracle.svm.reflect.proxy.DynamicProxySupport.getProxyClass(DynamicProxySupport.java:158)
	at java.lang.reflect.Proxy.getProxyConstructor(Proxy.java:48)
	at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:1037)
	at com.pi4j.provider.impl.DefaultRuntimeProviders.add(DefaultRuntimeProviders.java:267)
	at com.pi4j.provider.impl.DefaultRuntimeProviders.add(DefaultRuntimeProviders.java:242)
	at com.pi4j.provider.impl.DefaultRuntimeProviders.initialize(DefaultRuntimeProviders.java:373)
	at com.pi4j.runtime.impl.DefaultRuntime.initialize(DefaultRuntime.java:260)
	at com.pi4j.context.impl.DefaultContext.<init>(DefaultContext.java:103)
	at com.pi4j.context.impl.DefaultContext.newInstance(DefaultContext.java:72)
	at com.pi4j.context.impl.DefaultContextBuilder.build(DefaultContextBuilder.java:277)
	at com.pi4j.context.impl.DefaultContextBuilder.build(DefaultContextBuilder.java:48)
	at com.pi4j.Pi4J.newAutoContext(Pi4J.java:71)

Steps to recreate the issue:

Step 1: Download and unzip graalvm CE on ARM64 (raspberry pi)
Step 2: Run the below command to generate the native image

/home/rpi/graalvm-ce-java17-22.1.0/bin/native-image --no-fallback -H:DynamicProxyConfigurationFiles=/home/rpi/deps/proxy-config.json -jar /home/rpi/testApp.jar testApplication

Step 3: Contents of /home/rpi/deps/proxy-config.json

[
  {
    "interfaces":["com.pi4j.common.Describable","com.pi4j.provider.Provider","com.pi4j.extension.Extension","com.pi4j.common.Identity","com.pi4j.io.spi.SpiProvider","com.pi4j.plugin.raspberrypi.provider.spi.RpiSpiProvider","com.pi4j.common.Lifecycle"]}
  ,
  {
    "interfaces":["com.pi4j.common.Describable","com.pi4j.provider.Provider","com.pi4j.extension.Extension","com.pi4j.common.Identity","com.pi4j.plugin.raspberrypi.provider.serial.RpiSerialProvider","com.pi4j.io.serial.SerialProvider","com.pi4j.common.Lifecycle"]}
  ,
  {
    "interfaces":["com.pi4j.io.gpio.digital.DigitalOutputProvider","com.pi4j.io.gpio.GpioProvider","com.pi4j.common.Describable","com.pi4j.io.gpio.digital.DigitalProvider","com.pi4j.provider.Provider","com.pi4j.extension.Extension","com.pi4j.common.Identity","com.pi4j.plugin.raspberrypi.provider.gpio.digital.RpiDigitalOutputProvider","com.pi4j.common.Lifecycle"]}
  ,
  {
    "interfaces":["com.pi4j.io.i2c.I2CProvider","com.pi4j.common.Describable","com.pi4j.provider.Provider","com.pi4j.extension.Extension","com.pi4j.plugin.raspberrypi.provider.i2c.RpiI2CProvider","com.pi4j.common.Identity","com.pi4j.common.Lifecycle"]}
  ,
  {
    "interfaces":["com.pi4j.io.pwm.PwmProvider","com.pi4j.common.Describable","com.pi4j.provider.Provider","com.pi4j.extension.Extension","com.pi4j.common.Identity","com.pi4j.plugin.raspberrypi.provider.pwm.RpiPwmProvider","com.pi4j.common.Lifecycle"]}
  ,
  {
    "interfaces":["com.pi4j.plugin.raspberrypi.provider.gpio.digital.RpiDigitalInputProvider","com.pi4j.io.gpio.GpioProvider","com.pi4j.common.Describable","com.pi4j.io.gpio.digital.DigitalProvider","com.pi4j.provider.Provider","com.pi4j.extension.Extension","com.pi4j.common.Identity","com.pi4j.io.gpio.digital.DigitalInputProvider","com.pi4j.common.Lifecycle"]} 
]

I checked with the graalvm community (thanks to Vojin Jovanovic and Aleksandar Gradinac) and seems like the reason the native image is failing with the above exception is because - the order of proxy keeps changing and if the order doesn't match we will see above exception when trying to execute the native image. They recommend adding the proxies in the same order every time. Below are the snippets from my conversation with Aleksandar Gradinac - explaining what is going wrong:

one note regarding proxies: the order of interfaces matter, two proxies that specify the same interfaces but in different order result in two separate classes under the hood.
....
.
pi4j library could be iterating over a collection with an unstable iteration order in the library

Their recommendation was:

 tweak the library(pi4j) itself and remove the randomness of what they pass to the `newProxyInstance` call
the first randomness i see here is this HashSet - it has an undefined iteration order - https://github.com/Pi4J/pi4j-v2/blob/2.0/pi4j-core/src/main/java/com/pi4j/runtime/impl/DefaultRuntime.java#L213
@ganeshs4 ganeshs4 changed the title java native image fails due to randomness in loading the proxies graalvm java native image fails due to randomness in loading the proxies May 26, 2022
@gradinac
Copy link

One note: the above problem happens on the 2.0 release of the library, it seems like this particular issue has been fixed on the develop branch - #141

@eitch
Copy link
Member

eitch commented Sep 17, 2024

The proxies have been removed, so this shouldn't be an issue anymore.

@eitch eitch closed this as completed Sep 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants