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

Java 16 and 17 compatibility #191

Open
robertandrewbain opened this issue Apr 2, 2021 · 25 comments
Open

Java 16 and 17 compatibility #191

robertandrewbain opened this issue Apr 2, 2021 · 25 comments

Comments

@robertandrewbain
Copy link

Upgrading to Java 16 I receive the following Exception. I tried adding the VM option --add-opens java.base/java.lang=ALL-UNNAMED which I thought would work around the issue to no avail.

Exception in thread "main" java.lang.ExceptionInInitializerError
	at com.example.main(Example.java:10)
Caused by: net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InaccessibleObjectException-->Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @39aeed2f
	at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:464)
	at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:339)
	at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:96)
	at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:94)
	at net.sf.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at net.sf.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
	at net.sf.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
	at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:119)
	at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:294)
	at net.sf.cglib.core.KeyFactory$Generator.create(KeyFactory.java:221)
	at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:174)
	at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:153)
	at net.sf.cglib.proxy.Enhancer.<clinit>(Enhancer.java:73)
	... 1 more
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @39aeed2f
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:357)
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
	at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
	at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
	at net.sf.cglib.core.ReflectUtils$1.run(ReflectUtils.java:61)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:554)
	at net.sf.cglib.core.ReflectUtils.<clinit>(ReflectUtils.java:52)
	at net.sf.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:243)
	at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
	at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:332)
	... 13 more
@raphw
Copy link
Member

raphw commented Apr 2, 2021

Did you place cglib in a module? This is supposed to solve your problem. Alternatively, you can change the setting that forbids accessing internal API.

@robertandrewbain
Copy link
Author

robertandrewbain commented Apr 3, 2021

cglib is a transitive dependency so I can't put it in a module. As I mentioned above, --add-opens=java.base/java.lang=ALL-UNNAMED doesn't appear to work. Minimal reproducible example using Java 16:

import net.sf.cglib.proxy.Enhancer;

public class Main {
    public static void main(String[] args) {
        new Enhancer();
    }
}

@wind57
Copy link

wind57 commented Apr 6, 2021

@raphw can you please explain what you mean by you can change the setting that forbids accessing internal API.? thank you

@namannigam
Copy link

namannigam commented Apr 8, 2021

@wind57 This has been discussed here and an alternate approach for users (unless cglib plans to upgrade) is suggested. i.e to make use of the override --illegal-access=permit.

@cowwoc
Copy link

cowwoc commented May 26, 2021

I believe the correct fix for this problem would be for cglib to ship with a module-info.java that imports java.base. You can use multi-release JARs to maintain support for older JDKs. Search for multiReleaseOutput at https://www.baeldung.com/maven-multi-release-jars

@nmandrescu
Copy link

nmandrescu commented May 31, 2021

JEP 403 targeted for JDK 17 (release planned for Sept 2021) will remove --illegal-access flag. That will be equivalent to --illegal-access=deny.

cglib can go with standard replacements for the most commonly used internal elements of the JDK.
In this case instead of protected java.lang.ClassLoader::defineClass method use java.lang.invoke.MethodHandles.Lookup::defineClass (since JDK9).

@Venorcis
Copy link

Same issue here, using --illegal-access=permit is not an option for my users, especially with Java 17 coming up.

@rototor
Copy link

rototor commented Jul 15, 2021

FYI: I've just implemented an initial hacky workaround to make cglib some kind of work with JDK17. See this commit rototor@cc8632e

It's ugly because it needs to get a class in the package of the class going to be defined. To do so it does some "magic" with the class path, including (in my case) stripping "Wicket_Proxy_" prefixes.

Feel free to use this as a base to make a clean version of it. (The real solution for me would be if Wicket just migrated to ByteBuddy...)

@robertandrewbain robertandrewbain changed the title Java 16 compatibility Java 16 and 17 compatibility Aug 5, 2021
@robertandrewbain
Copy link
Author

Is there likely to be a Java 17 compatibility fix in the near future? I know Apache Wicket are affected by this and looking at putting in a fix but if a fix is planned at this end, they don't need to worry. https://issues.apache.org/jira/browse/WICKET-6913

@cowwoc
Copy link

cowwoc commented Sep 17, 2021

Instead of layering one hack on top of another, wouldn't it be better to implement this using public methods that are guaranteed to continue working in the future?

@adityajoshee
Copy link

Any update for the fix for java 17?

@cowwoc
Copy link

cowwoc commented Jan 23, 2022

Last commit to this project is August 2019. Methinks it's time to bury it.

@rototor
Copy link

rototor commented Jan 24, 2022

@adityajoshee I don't think that there will be a fixed release for JDK 17. If at any way possible you should migrate to ByteBuddy. If you have CGLib as dependency of some other library you use, you should try to migrate to the latest version of this library. E.g. Wicket and Hibernate already migrated away to ByteBuddy.

As a last resort you can use my commit rototor@cc8632e as a base for your own local built and deployed cglib version.

@sameb
Copy link
Contributor

sameb commented Jan 26, 2022

FYI all, I added a note to the top-level README about its current state:

IMPORTANT NOTE: cglib is unmaintained and does not work well (or possibly at all?) in newer JDKs, particularly JDK17+. If you need to support newer JDKs, we will accept well-tested well-thought-out patches... but you'll probably have better luck migrating to something like ByteBuddy.

@DanielThomas
Copy link

For those unable to migrate to ByteBuddy easily, Spring Framework maintains patches for cglib that include compatibility for Java 17, you could do a similar thing and embed cglib into your sources:

https://github.com/spring-projects/spring-framework/tree/main/spring-core/src/main/java/org/springframework/cglib

@buttercannfly
Copy link

try add jvm option
- JVM_OPTS= --add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.management/javax.management=ALL-UNNAMED --add-opens=java.naming/javax.naming=ALL-UNNAMED

@shuodashen
Copy link

For those unable to migrate to ByteBuddy easily, Spring Framework maintains patches for cglib that include compatibility for Java 17, you could do a similar thing and embed cglib into your sources:

https://github.com/spring-projects/spring-framework/tree/main/spring-core/src/main/java/org/springframework/cglib

I have replace cglib to the one embeded in spring framework, but the issue still occurs:

org.springframework.cglib.core.CodeGenerationException: java.lang.reflect.InaccessibleObjectException-->Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @385e9564
at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:598) ~[spring-core-5.3.23.jar:5.3.23]
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:363) ~[spring-core-5.3.23.jar:5.3.23]
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:110) ~[spring-core-5.3.23.jar:5.3.23]
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:108) ~[spring-core-5.3.23.jar:5.3.23]

@JJBRT
Copy link

JJBRT commented Oct 29, 2022

It can be solved without any JVM parameter with Burningwave Core reflection components that thanks to a special driver work on all JDKs from 8. In this case you can also simply call the method org.burningwave.core.assembler.StaticComponentContainer.Modules.exportAllToAll()

@KouShenhai
Copy link

try add jvm option - JVM_OPTS= --add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.management/javax.management=ALL-UNNAMED --add-opens=java.naming/javax.naming=ALL-UNNAMED

Problem solved,thank you very much

jeantessier added a commit to jeantessier/dependency-finder that referenced this issue Feb 11, 2023
Switched to ByteBuddy for the imposteriser.  I was using `cglib` before,
but it is not compatible with Java 16+ and there are no signs it will
get fixed any time soon.  I can now compile and run tests using Java 19.

cglib/cglib#191

The JUnit 4 integration needed a different `Mockery`, for some reason.

I had to add a no-arg constructor to `ConstantPool` so that jMock could
mock it with the new ByteBuddy imposteriser.

ByteBuddy has a lot of difficulty imposterizing some classes.  One test
was trying to mock `PrintWriter` and I had to rewrite it to validate the
output using a wrapped `StringWriter` instead.
@ilwsm
Copy link

ilwsm commented Mar 7, 2023

try add jvm option - JVM_OPTS= --add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.management/javax.management=ALL-UNNAMED --add-opens=java.naming/javax.naming=ALL-UNNAMED

Problem solved,thank you very much

How do it in Idea?

@Garlic6694
Copy link

just use spring-core cglib,do not need to change code:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
    </dependency>

import org.springframework.cglib.proxy.Enhancer;

@KamakshaiahM
Copy link

KamakshaiahM commented Sep 27, 2023

try add jvm option - JVM_OPTS= --add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.management/javax.management=ALL-UNNAMED --add-opens=java.naming/javax.naming=ALL-UNNAMED

Problem solved,thank you very much

Hi - Can you please where and how did you added these jvm options? I am using maven, spring boot latest versions, while migrating to jdk 17 i am getting InaccessibleObjectException, please advise. Thanks,

@KouShenhai
Copy link

KouShenhai commented Sep 27, 2023

尝试添加 JVM 选项- JVM_OPTS= --add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.management/javax.management=ALL-UNNAMED --add-opens=java.naming/javax.naming=ALL-UNNAMED

问题解决了,非常感谢

嗨 - 您能否请问您在哪里以及如何添加这些 jvm 选项?我正在使用 maven,Spring 启动最新版本,在迁移到 jdk 17 时,我遇到了无法访问的对象异常,请告知。谢谢

网上一大把

https://blog.51cto.com/Saintmm/5573298

@KamakshaiahM
Copy link

For those unable to migrate to ByteBuddy easily, Spring Framework maintains patches for cglib that include compatibility for Java 17, you could do a similar thing and embed cglib into your sources:
https://github.com/spring-projects/spring-framework/tree/main/spring-core/src/main/java/org/springframework/cglib

I have replace cglib to the one embeded in spring framework, but the issue still occurs:

org.springframework.cglib.core.CodeGenerationException: java.lang.reflect.InaccessibleObjectException-->Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @385e9564 at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:598) ~[spring-core-5.3.23.jar:5.3.23] at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:363) ~[spring-core-5.3.23.jar:5.3.23] at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:110) ~[spring-core-5.3.23.jar:5.3.23] at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:108) ~[spring-core-5.3.23.jar:5.3.23]

Hi, did you get this working? Please advise how did you solved this issue?

@isMrZhang
Copy link

I seem to have found the answer, it works fine on spring-core-6.0.15 and the key to the fix lies in this patch.
image
spring-projects/spring-framework#28699

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