Quarkus: field injection of package-private fields for subclasses in dependent modules fails with IllegalAccessError

Created on 19 Feb 2020  路  22Comments  路  Source: quarkusio/quarkus

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:

  1. Build trivial "common" module: https://github.com/jordanglassman/quarkus-cdi-bug-common
  2. Run quarkus app that depends on "common": https://github.com/jordanglassman/quarkus-cdi-bug-app
  3. cause class to be loaded with curl http://localhost:8080/hello
  4. observe Caused by: java.lang.IllegalAccessError: tried to access field... when class is loaded

Environment (please complete the following information):

  • Output of 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
  • Output of 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)
  • GraalVM version (if different from Java):
    N/A
  • Quarkus version or git rev:
    1.2.1Final

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).

arearc kinbug

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.

All 22 comments

+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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

GregJohnStewart picture GregJohnStewart  路  51Comments

cescoffier picture cescoffier  路  43Comments

quarkusbot picture quarkusbot  路  152Comments

rdifrango picture rdifrango  路  62Comments

dirkweil picture dirkweil  路  79Comments