Describe the bug
When a project extends classes in another jar, field injection on those subclasses with package-private or protected accessibility is failing with IllegalAccessError.
Expected behavior
Should be able to extend subclasses in a dependent JAR and have field injection of base classes work normally.
Actual behavior
Caused by: java.lang.IllegalAccessError: tried to access field org.acme.quickstart.MyBaseService.configStoreEndpoint from class org.acme.quickstart.MyService_Bean
at org.acme.quickstart.MyService_Bean.create(MyService_Bean.zig:685)
at org.acme.quickstart.MyService_Bean.create(MyService_Bean.zig:579)
at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:80)
at io.quarkus.arc.impl.ComputingCache$CacheFunction.lambda$apply$0(ComputingCache.java:99)
at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
at io.quarkus.arc.impl.ComputingCache.getValue(ComputingCache.java:41)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:25)
at org.acme.quickstart.MyService_ClientProxy.arc$delegate(MyService_ClientProxy.zig:124)
at org.acme.quickstart.MyService_ClientProxy.getKeyPrefix(MyService_ClientProxy.zig:275)
at org.acme.quickstart.GreetingResource.hello(GreetingResource.java:25)
at org.acme.quickstart.GreetingResource_ClientProxy.hello(GreetingResource_ClientProxy.zig:190)
To Reproduce
Steps to reproduce the behavior:
curl http://localhost:8080/helloCaused by: java.lang.IllegalAccessError: tried to access field... when class is loadedEnvironment (please complete the following information):
uname -a or ver: $ uname -a
Darwin ip-192-168-1-137.ec2.internal 18.2.0 Darwin Kernel Version 18.2.0: Mon Nov 12 20:24:46 PST 2018; root:xnu-4903.231.4~2/RELEASE_X86_64 x86_64
java -version: $ java -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
Additional context
I noticed that the problem does not occur if the "common" module is part of the quarkus app project (ie. a standalone maven module in the quarkus app project).
+1
cc @mkouba
+1
@jordanglassman Could you pls try with the latest 1.3.0.Alpha2? Looks like a classloading issue and 1.3 brings a big classloader change that could potentially fix your problem.
@mkouba quarkus doesn't start up with 1.3.0.Alpha2 for what looks like unrelated reasons:
[INFO] --- quarkus-maven-plugin:1.2.1.Final:dev (default-cli) @ getting-started ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to /Users/jglassman/iiworkspace/getting-started/target/classes
Listening for transport dt_socket at address: 5005
08:33:32,426 INFO [org.jbo.threads] JBoss Threads version 3.0.0.Final
08:33:32,595 ERROR [io.qua.dev.DevModeMain] Failed to start Quarkus: java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[error]: Build step io.quarkus.arc.deployment.BeanArchiveProcessor#build threw an exception: java.lang.NoSuchMethodError: io.quarkus.arc.processor.BeanArchives.buildBeanArchiveIndex([Lorg/jboss/jandex/IndexView;)Lorg/jboss/jandex/IndexView;
at io.quarkus.arc.deployment.BeanArchiveProcessor.build(BeanArchiveProcessor.java:77)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at io.quarkus.deployment.ExtensionLoader$2.execute(ExtensionLoader.java:915)
at io.quarkus.builder.BuildContext.run(BuildContext.java:279)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2011)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1535)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1426)
at java.lang.Thread.run(Thread.java:748)
at org.jboss.threads.JBossThread.run(JBossThread.java:479)
at io.quarkus.runner.RuntimeRunner.run(RuntimeRunner.java:181)
at io.quarkus.dev.DevModeMain.doStart(DevModeMain.java:178)
at io.quarkus.dev.DevModeMain.start(DevModeMain.java:96)
at io.quarkus.dev.DevModeMain.main(DevModeMain.java:67)
Caused by: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[error]: Build step io.quarkus.arc.deployment.BeanArchiveProcessor#build threw an exception: java.lang.NoSuchMethodError: io.quarkus.arc.processor.BeanArchives.buildBeanArchiveIndex([Lorg/jboss/jandex/IndexView;)Lorg/jboss/jandex/IndexView;
at io.quarkus.arc.deployment.BeanArchiveProcessor.build(BeanArchiveProcessor.java:77)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at io.quarkus.deployment.ExtensionLoader$2.execute(ExtensionLoader.java:915)
at io.quarkus.builder.BuildContext.run(BuildContext.java:279)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2011)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1535)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1426)
at java.lang.Thread.run(Thread.java:748)
at org.jboss.threads.JBossThread.run(JBossThread.java:479)
at io.quarkus.builder.Execution.run(Execution.java:108)
at io.quarkus.builder.BuildExecutionBuilder.execute(BuildExecutionBuilder.java:79)
at io.quarkus.deployment.QuarkusAugmentor.run(QuarkusAugmentor.java:128)
at io.quarkus.runner.RuntimeRunner.run(RuntimeRunner.java:114)
... 3 more
Caused by: java.lang.NoSuchMethodError: io.quarkus.arc.processor.BeanArchives.buildBeanArchiveIndex([Lorg/jboss/jandex/IndexView;)Lorg/jboss/jandex/IndexView;
at io.quarkus.arc.deployment.BeanArchiveProcessor.build(BeanArchiveProcessor.java:77)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at io.quarkus.deployment.ExtensionLoader$2.execute(ExtensionLoader.java:915)
at io.quarkus.builder.BuildContext.run(BuildContext.java:279)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2011)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1535)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1426)
at java.lang.Thread.run(Thread.java:748)
at org.jboss.threads.JBossThread.run(JBossThread.java:479)
08:33:32,596 INFO [io.qua.dev.DevModeMain] Attempting to start hot replacement endpoint to recover from previous Quarkus startup failure
08:33:32,605 ERROR [io.qua.dev.DevModeMain] Failed to start quarkus: java.lang.IllegalArgumentException: workerPoolSize must be > 0
at io.vertx.core.VertxOptions.setWorkerPoolSize(VertxOptions.java:275)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder.convertToVertxOptions(VertxCoreRecorder.java:152)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder.initializeWeb(VertxCoreRecorder.java:105)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder.startServerAfterFailedStart(VertxHttpRecorder.java:119)
at io.quarkus.vertx.http.deployment.devmode.VertxHotReplacementSetup.handleFailedInitialStart(VertxHotReplacementSetup.java:30)
at io.quarkus.dev.RuntimeUpdatesProcessor.startupFailed(RuntimeUpdatesProcessor.java:452)
at io.quarkus.dev.DevModeMain.doStart(DevModeMain.java:192)
at io.quarkus.dev.DevModeMain.start(DevModeMain.java:96)
at io.quarkus.dev.DevModeMain.main(DevModeMain.java:67)
Reproducer project branches:
https://github.com/jordanglassman/quarkus-cdi-bug-app/tree/1.3.0.Alpha2
https://github.com/jordanglassman/quarkus-cdi-bug-common/tree/1.3.0.Alpha2
This needs to be bumped as well https://github.com/jordanglassman/quarkus-cdi-bug-app/blob/1.3.0.Alpha2/pom.xml#L23 :)
Sorry, didn't see 1.3.0.Alpha2 here, will try removing the BOM.
You don't have to remove the bom, you can just use quarkus-bom instead of quarkus-universe-bom
@geoand same result:
[INFO] --- quarkus-maven-plugin:1.3.0.Alpha2:dev (default-cli) @ getting-started ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to /Users/jglassman/iiworkspace/getting-started/target/classes
Listening for transport dt_socket at address: 5005
2020-02-20 08:49:38,403 INFO [io.quarkus] (main) getting-started 1.0-SNAPSHOT (running on Quarkus 1.3.0.Alpha2) started in 0.974s. Listening on: http://0.0.0.0:8084
2020-02-20 08:49:38,407 INFO [io.quarkus] (main) Profile dev activated. Live Coding activated.
2020-02-20 08:49:38,407 INFO [io.quarkus] (main) Installed features: [cdi, resteasy]
2020-02-20 08:49:43,942 INFO [org.acm.qui.GreetingResource] (executor-thread-1) init
2020-02-20 08:49:43,944 INFO [org.acm.qui.GreetingResource] (executor-thread-1) hello!
2020-02-20 08:49:43,949 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (executor-thread-1) HTTP Request to /hello failed, error id: 09851d9c-9aea-4dec-9e44-faeb9be2e543-1: org.jboss.resteasy.spi.UnhandledException: java.lang.IllegalAccessError: tried to access field org.acme.quickstart.MyBaseService.configStoreEndpoint from class org.acme.quickstart.MyService_Bean
at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:106)
at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:372)
at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:209)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:496)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:252)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:153)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:363)
at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:156)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:238)
at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:120)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.access$000(VertxRequestHandler.java:36)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler$1.run(VertxRequestHandler.java:85)
at io.quarkus.runtime.CleanableExecutor$CleaningRunnable.run(CleanableExecutor.java:224)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2027)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1551)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1411)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at java.lang.Thread.run(Thread.java:748)
at org.jboss.threads.JBossThread.run(JBossThread.java:479)
Caused by: java.lang.IllegalAccessError: tried to access field org.acme.quickstart.MyBaseService.configStoreEndpoint from class org.acme.quickstart.MyService_Bean
at org.acme.quickstart.MyService_Bean.create(MyService_Bean.zig:640)
at org.acme.quickstart.MyService_Bean.create(MyService_Bean.zig:534)
at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:80)
at io.quarkus.arc.impl.ComputingCache$CacheFunction.lambda$apply$0(ComputingCache.java:99)
at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
at io.quarkus.arc.impl.ComputingCache.getValue(ComputingCache.java:41)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:25)
at org.acme.quickstart.MyService_ClientProxy.arc$delegate(MyService_ClientProxy.zig:124)
at org.acme.quickstart.MyService_ClientProxy.getKeyPrefix(MyService_ClientProxy.zig:275)
at org.acme.quickstart.GreetingResource.hello(GreetingResource.java:25)
Repro projects updated:
https://github.com/jordanglassman/quarkus-cdi-bug-app/tree/1.3.0.Alpha2
https://github.com/jordanglassman/quarkus-cdi-bug-common/tree/1.3.0.Alpha2
Thanks for checking @jordanglassman !
/cc @mkouba @stuartwdouglas looks like something we would want to get fixed for 1.3.
I'm just looking at it...
So I've just tried the reproducer and the problem only occurs in the development mode (mvn compile quarkus:dev). MyBaseService is loaded by a different class loader than MyService and MyService_Bean.
I'll try to identify the problem but we will probably need to wait for @stuartwdouglas...
I think that it would work fine if quarkus-cdi-bug-common was part of a multi-module Maven project together with quarkus-cdi-bug-app. However, in the current setup Quarkus has no way to detect what classes from the quarkus-cdi-bug-common should be loaded by the CL that supports hot replacement.
I think that it would work fine if quarkus-cdi-bug-common was part of a multi-module Maven
@mkouba I can confirm this is the case. This issue was discovered while extracting a common module from a multi-module Maven project to a standalone jar.
/cc @stuartwdouglas
I would be tempted to just say that we don't support split packages (the same package split between multiple jars).
This is just a bad practice generally, and when you have them loaded by different class loaders it will just cause confusion, in dev and test, even though it would work in production mode.
Note that even if we changed this to use reflection this case could still fail as the split packages mean that there are two different packages, this means that some method/field accesses may be disallowed by the JVM itself.
I agree with Stuart. In fact, I missed the fact that the reproducer app is using split packages.
AFAIK it's not only bad practice but it's also unsupported by JPMS (JDK9+).
Should we have that in the docs somewhere? The problem is where... CDI docs maybe?
I don't think it's a CDI-specific problem... Maybe we should test a package-private method access first?
I think the best we can do here is to detect split packages.
Most helpful comment
I would be tempted to just say that we don't support split packages (the same package split between multiple jars).
This is just a bad practice generally, and when you have them loaded by different class loaders it will just cause confusion, in dev and test, even though it would work in production mode.