Community
Participate
Working Groups
conditions: java -javaagent:libs/aspectjweaver-1.9.2.jar -jar .\target\my-spring-boot-2.1-application.war java 11 result: ---- . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.3.RELEASE) WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access using Lookup on org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor (file: aspectjweaver-1.9.2.jar) to class java.lang.ClassLoader WARNING: Please consider reporting this to the maintainers of org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations WARNING: All illegal access operations will be denied in a future release ----
Removed, user request
If you set --illegal-access=deny then you get a useful message: java.lang.IllegalAccessException: module java.base does not open java.lang to unnamed module @3532ec19 So then we can set --add-opens: java --add-opens java.base/java.lang=ALL-UNNAMED -javaagent:blahblahblah And this removes the message. Is that a viable option for you? I'm not sure yet if I can turn that option into something I can set in an aspectjweaver module definition.
this is a fine option - have implemented in production. is this a problem with java 11? does it need to be reported to someone? we are standardizing on java 11 for now.
I would say it isn't a bug - it is more that Java11 is more strict about who can do what. (Feels a bit like when java started requiring the use of verification stack maps in class files - there was one version of java that used them if they were there but was ok if they were missing and the requirement was going to fully be enforced for the next release). I would think AspectJ will do things differently down the line when this is finally not possible in a later version of the JDK. I'm just not clear what the alternative is right now or I'd move to it. I do remember some folks proposing an API we'd like to see in the JDK that would be a much better solution. If/when that appears I'll move to it but I don't *think* it is there yet (although I haven't been following progress closely). Glad you are ok with that proposed option.
Much thanks - What do you think about adding this to the aspecj getting started guides? I imagine that it impacts alot of folks who use jdk9+ until a better solution is found.
I think it will definitely go in the next README. I never seem to find the time to merge readmes into the real docs. If it is the readme then people should find it on a search for the error.
Put the add opens option in the readme for 1.9.4
The other supported API in Java SE for injecting classes is Lookup.defineClass, maybe this project could look at that instead.
Hey Alan - if you read this - what I have now is Unsafe use for older JDKs, and using the MethodHandle.Lookup.defineClass option for Java 11. However, that requirement that the Lookup instance is for the same protectiondomain/runtime package as the class being defined is still painful. Has anything changed lately to make that easier? I saw the discussion in http://mail.openjdk.java.net/pipermail/jigsaw-dev/2018-April/013754.html a while ago and hoped there might something like the options Rafael proposed in there by now. I found a couple of JDK issues but they didn't seem to go anywhere https://bugs.openjdk.java.net/browse/JDK-8200559 / https://bugs.openjdk.java.net/browse/JDK-8205386
Hi Andrew, can you say more how you get Lookup object? MethodHandles::privateLookupIn intends to help the frameworks library to get a private Lookup object on a target class. Does that help?
Hi Mandy - what is happening is that in the middle of transforming some bytes for a class we have needed to generate a closure class to support implementation of some around advice on something in that class. I need to register that closure alongside the affected target but at the time the generation is happening, the affected target bytes are still being transformed (we're in a JVM bytecode transformer implmentation), we haven't defined the class yet, so I can't do a lookup on that target class that I want to put it alongside. (I will admit I'm no expect in this area, please correct me if I'm wrong somewhere here...) Due to being on Java 8 for compilation, but wanting to run on 11, it is all loaded via reflection, so rather painful to look at. I think I saw this pattern used elsewhere and it is working for me apart from that message. I'll pull out the steps here but the full painful code is below. Am I looking up on the wrong thing? Thanks for taking a look MethodType defineClassMethodType = MethodType.methodType(Class.class, new Class[]{String.class, byte[].class, int.class, int.class, ProtectionDomain.class}); MethodHandles.Lookup methodHandlesLookup = MethodHandles.lookup(); MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(ClassLoader.class, methodHandlesLookup); MethodHandle defineClassMethodHandle = lookup.findVirtual(ClassLoader.class, "defineClass", defineClassMethodType); clazz = defineClassMethodHandle.bindTo(loader).invokeWithArguments(name, bytes, 0, bytes.length); // MethodType defineClassMethodType = MethodType.methodType(Class.class, new Class[]{String.class, byte[].class, int.class, int.class, ProtectionDomain.class}); Class<?> methodType_Class = Class.forName("java.lang.invoke.MethodType"); Method methodTypeMethodOnMethodTypeClass = methodType_Class.getDeclaredMethod("methodType", Class.class,Class[].class); methodTypeMethodOnMethodTypeClass.setAccessible(true); Object defineClassMethodType = methodTypeMethodOnMethodTypeClass.invoke(null, Class.class, new Class[] {String.class,byte[].class,int.class,int.class,ProtectionDomain.class}); // MethodHandles.Lookup methodHandlesLookup = MethodHandles.lookup(); Class<?> methodHandles_Class = Class.forName("java.lang.invoke.MethodHandles"); Method lookupMethodOnMethodHandlesClass = methodHandles_Class.getDeclaredMethod("lookup"); lookupMethodOnMethodHandlesClass.setAccessible(true); Object methodHandlesLookup = lookupMethodOnMethodHandlesClass.invoke(null); // MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(ClassLoader.class, methodHandlesLookup); Class<?> methodHandlesLookup_Class = Class.forName("java.lang.invoke.MethodHandles$Lookup"); Method privateLookupMethodOnMethodHandlesClass = methodHandles_Class.getDeclaredMethod("privateLookupIn",Class.class,methodHandlesLookup_Class); privateLookupMethodOnMethodHandlesClass.setAccessible(true); Object lookup = privateLookupMethodOnMethodHandlesClass.invoke(null, ClassLoader.class, methodHandlesLookup); // MethodHandle defineClassMethodHandle = lookup.findVirtual(ClassLoader.class, "defineClass", defineClassMethodType); Method findVirtual_Method = methodHandlesLookup_Class.getDeclaredMethod("findVirtual", Class.class,String.class,methodType_Class); findVirtual_Method.setAccessible(true); defineClassMethodHandle = findVirtual_Method.invoke(lookup, ClassLoader.class, "defineClass",defineClassMethodType); // clazz = defineClassMethodHandle.bindTo(loader).invokeWithArguments(name, bytes, 0, bytes.length); Class<?> methodHandle_Class = Class.forName("java.lang.invoke.MethodHandle"); bindTo_Method = methodHandle_Class.getDeclaredMethod("bindTo", Object.class); invokeWithArguments_Method = methodHandle_Class.getDeclaredMethod("invokeWithArguments",Object[].class);
Hi Andrew, I only checked your reply now. W.r.t. compiling on JDK 8 and running on 11, Multi-Release JAR [1] should help (which allows you to code using the new APIs rather than reflection). The example code isn't clear to me if you are still calling ClassLoader::defineClass or MethodHandles::privateLookupIn + Lookup::defineClass. But I think I see your issue as an agent who is transforming a class to call an auxiliary class (generated by the agent) does not have the Lookup object on the target class to begin with. Looks like you only want to inject the class in the same package as the target class and the proposed API by https://bugs.openjdk.java.net/browse/JDK-8200559 would satisfy your need. Can you confirm my understanding? [1] https://openjdk.java.net/jeps/238
This is now a probleme in jdk16 Cannot invoke "java.lang.reflect.Method.invoke(Object, Object[])" because "org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.bindTo_Method" is null java.lang.NullPointerException: Cannot invoke "java.lang.reflect.Method.invoke(Object, Object[])" because "org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.bindTo_Method" is null at org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.defineClass(ClassLoaderWeavingAdaptor.java:1102) at org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.access$300(ClassLoaderWeavingAdaptor.java:66) at org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor$SimpleGeneratedClassHandler.acceptClass(ClassLoaderWeavingAdaptor.java:150) at org.aspectj.weaver.tools.WeavingAdaptor$WeavingClassFileProvider$1.acceptResult(WeavingAdaptor.java:920) at org.aspectj.weaver.bcel.BcelWeaver.weaveAndNotify(BcelWeaver.java:1434) at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:1195) at org.aspectj.weaver.tools.WeavingAdaptor.getWovenBytes(WeavingAdaptor.java:551) at org.aspectj.weaver.tools.WeavingAdaptor.weaveClass(WeavingAdaptor.java:387) at org.aspectj.weaver.loadtime.Aj.preProcess(Aj.java:116) at org.aspectj.weaver.loadtime.ClassPreProcessorAgentAdapter.transform(ClassPreProcessorAgentAdapter.java:51) at java.instrument/java.lang.instrument.ClassFileTransformer.transform(ClassFileTransformer.java:244) at java.instrument/sun.instrument.TransformerManager.transform(TransformerManager.java:188) at java.instrument/sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:565) at java.base/java.lang.ClassLoader.defineClass1(Native Method) at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1010) at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150) at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:512) at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:420) at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:414) at java.base/java.security.AccessController.doPrivileged(AccessController.java:691) at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:413) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:586) at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:519) at java.base/java.lang.Class.forName0(Native Method) at java.base/java.lang.Class.forName(Class.java:466) at org.springframework.util.ClassUtils.forName(ClassUtils.java:284) at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:469) at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1607) at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1534) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:693) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:663) at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1670) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:570) at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:542) at org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletRegistrationCondition.checkServletRegistration(DispatcherServletAutoConfiguration.java:187) at org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletRegistrationCondition.getMatchOutcome(DispatcherServletAutoConfiguration.java:167) at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47) at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108) at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:226) at org.springframework.context.annotation.ConfigurationClassParser.processMemberClasses(ConfigurationClassParser.java:372) at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:272) at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250) at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:600) at org.springframework.context.annotation.ConfigurationClassParser.access$800(ConfigurationClassParser.java:111) at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.lambda$processGroupImports$1(ConfigurationClassParser.java:812) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.processGroupImports(ConfigurationClassParser.java:809) at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorHandler.process(ConfigurationClassParser.java:780) at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:193) at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:336) at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:252) at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:285) at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:99) at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:751) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:569) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426) at org.springframework.boot.SpringApplication.run(SpringApplication.java:326) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) at fr.vinthec.StarterApplication.main(StarterApplication.java:19) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:567) at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) at org.springframework.boot.loader.Launcher.launch(Launcher.java:107) at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
I can comfirm that for the upcoming AspectJ 1.9.7 we do not have a solution, but instead are documenting the need to use this on JDK 16+: --add-opens java.base/java.lang=ALL-UNNAMED https://github.com/eclipse/org.aspectj/blob/d17189c430a7ffd1ec966759a93b3ed348766650/docs/dist/doc/README-197.html#L71-L79 I only started contributing to AspectJ a few months back and am not competent (yet) to find out, if we can avoid that. Unfortunately, Andy is busy and did not have time to dig in either. If we cannot find a solution, this additional CLI parameter might well be a deal breaker for many users in the future with regard to AspectJ LTW. @Andy, can you maybe comment on this, answering Mandy's question? > I think I see your issue as an agent who is transforming a class to call > an auxiliary class (generated by the agent) does not have the Lookup > object on the target class to begin with. Looks like you only want to > inject the class in the same package as the target class and the proposed > API by https://bugs.openjdk.java.net/browse/JDK-8200559 would satisfy your > need. > > Can you confirm my understanding?