spring-framework icon indicating copy to clipboard operation
spring-framework copied to clipboard

Support for CGLIB BeanCopier utility on JDK 17 still error

Open SuperEdison opened this issue 2 years ago • 13 comments

springframework.version 5.3.21 jdk.version 17

old issues I find this error still happening that is fault way to use? public static void main(String[] args) { BeanCopier beanCopier = BeanCopier.create(A.class, B.class, false); } Exception in thread "main" 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 @32cf48b7 at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:589) at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:363) at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:110) at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:108) at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54) at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java) at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61) at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34) at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:134) at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:319) at org.springframework.cglib.beans.BeanCopier$Generator.create(BeanCopier.java:98) at org.springframework.cglib.beans.BeanCopier.create(BeanCopier.java:52) at club.edm.bscwallet.server.BscWalletApplication.main(BscWalletApplication.java:17) 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 @32cf48b7 at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354) 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 org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:553) ... 13 more

    public static void main(String[] args) {
        BeanCopier beanCopier = BeanCopier.create(A.class, B.class, false);
        System.out.println(beanCopier);
        A a = new A();
    }

    static public class A {

    }

    static public class B {

    }

@jhoeller

SuperEdison avatar Jun 24 '22 10:06 SuperEdison

This didn't happen with any errors,I tried using spring-core 6.0.0M4 and spring-core 5.3.21,didn't get any errors

public class AppTest {

    @Test
    public void test() {
        BeanCopier copier = BeanCopier.create(A.class, B.class, false);
        System.out.println("copier:" + copier);
    }
}

class A {

}

class B {

}

livk-cloud avatar Jun 27 '22 05:06 livk-cloud

这没有发生任何错误,我尝试使用 spring-core 6.0.0M4 和 spring-core 5.3.21,没有收到任何错误

public class AppTest {

    @Test
    public void test() {
        BeanCopier copier = BeanCopier.create(A.class, B.class, false);
        System.out.println("copier:" + copier);
    }
}

class A {

}

class B {

}

because your class not public class, you can try create public class A and B

SuperEdison avatar Jun 27 '22 10:06 SuperEdison

这没有发生错误,我试用使用 spring-core 6.0.0M4 和 spring-core 5.3.21,没有收到任何错误

public class AppTest {

    @Test
    public void test() {
        BeanCopier copier = BeanCopier.create(A.class, B.class, false);
        System.out.println("copier:" + copier);
    }
}

class A {

}

class B {

}

因为您的课程不是公共课程,您可以尝试创建公共课程 A 和 B

Obviously there is no problem

image

spring6.0.0-M4 result image

spring5.3.21 result image

livk-cloud avatar Jun 27 '22 10:06 livk-cloud

这没有发生错误,我试用使用 spring-core 6.0.0M4 和 spring-core 5.3.21,没有收到任何错误

public class AppTest {

    @Test
    public void test() {
        BeanCopier copier = BeanCopier.create(A.class, B.class, false);
        System.out.println("copier:" + copier);
    }
}

class A {

}

class B {

}

因为您的课程不是公共课程,您可以尝试创建公共课程 A 和 B

Obviously there is no problem

image

spring6.0.0-M4 result image

spring5.3.21 result image

image image

so, i wanna know that you add some param? there are pic to tell you my env and spring.verison.

SuperEdison avatar Jun 28 '22 07:06 SuperEdison

class A and class B is empty I am using oracle jdk17.0.2 spring version has been said before

livk-cloud avatar Jun 28 '22 08:06 livk-cloud

class A and class B is empty

I am using oracle jdk17.0.2

spring version has been said before

can you show me the A class code ?

SuperEdison avatar Jun 28 '22 08:06 SuperEdison

A类和B类为空

我正在使用 oracle jdk17.0.2

spring 版本之前已经说过了

你能告诉我A类代码吗?

image

image

livk-cloud avatar Jun 28 '22 08:06 livk-cloud

A类和B类为空

我正在使用 oracle jdk17.0.2

spring 版本之前已经说过了

你能告诉我A类代码吗?

image

image

i had change oracle jdk17,still error. i have no idea to solve it. do you add --add-opens java.base/java.lang=ALL-UNNAMED param?

SuperEdison avatar Jun 28 '22 10:06 SuperEdison

A类和B类为空

我正在使用 oracle jdk17.0.2

spring 之前已经知道了

你能告诉我一个类代码吗?

图片 图片

我改变了oracle jdk17,仍然错误。 我不知道解决它。 你添加--add-opens java.base/java.lang=ALL-UNNAMED 参数吗?

No, I use the default parameters of the idea, I think you should use @Test instead of the Main method

livk-cloud avatar Jun 29 '22 01:06 livk-cloud

i try many way to solve this problem, but any way had fail

SuperEdison avatar Jun 30 '22 03:06 SuperEdison

i try many way to solve this problem, but any way had fail

me too

funky-eyes avatar Aug 17 '22 15:08 funky-eyes

Same issue. Here is minimize steps:

  1. create empty springboot project using spring initializr(in IDEA) Project SDK: openjdk 17.0.3 Java: 17 SpringBoot Version 2.7.3 SpringFramework Version 5.3.22
  2. create two entity class, Person.class / PersonVO.class for example
public class Person {
    String name;
    Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
import java.util.List;

public class PersonVO extends Person {
    List<String> hobbies;

    public List<String> getHobbies() {
        return hobbies;
    }

    public void setHobbies(List<String> hobbies) {
        this.hobbies = hobbies;
    }
}
  1. use BeanCopier
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cglib.beans.BeanCopier;

@SpringBootApplication
public class BeanCopierDemoApplication {
    private static final Log logger = LogFactory.getLog(BeanCopierDemoApplication.class);

    public static void main(String[] args) {
        PersonVO personVO = testBeanCopy();
        logger.info(personVO);
        SpringApplication.run(BeanCopierDemoApplication.class, args);
    }

    public static PersonVO testBeanCopy() {
        Person person = new Person();
        person.setName("nico");
        person.setAge(18);
        PersonVO personVO = new PersonVO();
        final BeanCopier beanCopier = BeanCopier.create(Person.class, PersonVO.class, false);
        beanCopier.copy(person, personVO, null);
        personVO.setHobbies(null);
        return personVO;
    }
}
  1. start springboot application and error occurred
Exception in thread "main" 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 @7920ba90
	at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:598)
	at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:363)
	at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:110)
	at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:108)
	at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
	at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
	at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:134)
	at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:319)
	at org.springframework.cglib.beans.BeanCopier$Generator.create(BeanCopier.java:98)
	at org.springframework.cglib.beans.BeanCopier.create(BeanCopier.java:52)
	at com.example.beancopierdemo.BeanCopierDemoApplication.testBeanCopy(BeanCopierDemoApplication.java:24)
	at com.example.beancopierdemo.BeanCopierDemoApplication.main(BeanCopierDemoApplication.java:14)
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 @7920ba90
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
	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 org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:552)
	... 13 more

In my case, to resolve it, just add vm options "--add-opens java.base/java.lang=ALL-UNNAMED" 图片

So i think maybe it's a compatibility issue with CGLIB? If there are other solutions or information, that will be very grateful.

mazhewei avatar Sep 22 '22 06:09 mazhewei

@mazhewei, thank you, your post was very helpful for me!

invzbl3 avatar Nov 01 '22 14:11 invzbl3

I had a similar problem and after taking the answer from @mazhewei and @invzbl3 got it working.

The main problem here could be a Intellij-Settings-Problem.

For me following Setting for the argLine for the Tests with Maven was disabled.

Unbenannt

So when i runned the Test in the console with mvn clean install Test was ok but into IntelliJ was failed.

Then i wrote in the pom.xml some configuration for the surefire plugin:

<plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>${maven-surefire-plugin.version}</version>
                    <configuration>
                        <argLine>
                            --add-opens java.base/java.lang=ALL-UNNAMED
                            --add-opens java.base/java.lang.invoke=ALL-UNNAMED
                            --add-opens java.base/java.lang.reflect=ALL-UNNAMED
                            --add-opens java.base/java.util=ALL-UNNAMED
                            --add-opens java.base/java.text=ALL-UNNAMED
                            --add-opens java.desktop/java.awt.font=ALL-UNNAMED
                            --add-opens java.desktop/java.awt.geom=ALL-UNNAMED
                            @{surefireArgLine}
                        </argLine>
                    </configuration>
                </plugin>

In my case, i have more package/module opened because of another tests but the point is after doing this i had not to write the add-opens package/module for the single test.

Maybe @SuperEdison could try this solution and if all is fine issue could be close.

harryssuperman avatar Dec 02 '22 22:12 harryssuperman

我也遇到这种问题. 加了--add-opens也不好使.

ccwxl avatar Feb 09 '23 02:02 ccwxl

--add-opens java.base/java.lang=ALL-UNNAMED adding this parameter isn't actually a solution and doesn't mean JDK17 is actually supported

funky-eyes avatar Mar 09 '23 15:03 funky-eyes

--add-opens java.base/java.lang=ALL-UNNAMED adding this parameter isn't actually a solution and doesn't mean JDK17 is actually supported

yes, i agree

SuperEdison avatar Aug 18 '23 09:08 SuperEdison

Same problem here. add a mark to be notified.

johnny2002 avatar Oct 08 '23 06:10 johnny2002

BTW, I am using the latest version spring 6.0.12

johnny2002 avatar Oct 08 '23 06:10 johnny2002

This is a cglib issue, not a spring issue. Please report that against the cglib project.

snicoll avatar Oct 14 '23 07:10 snicoll

This is a cglib issue, not a spring issue. Please report that against the cglib project.

so could the spring cancel cglib support?

SuperEdison avatar Oct 14 '23 08:10 SuperEdison

It seems this is actually an issue with our context class patch which only works for non-public classes but not for public classes. I got a fix ready to be rolled into 6.0.14, to be backported to 5.3.31 as well.

That said, please note that Spring's repackaged CGLIB fork is not meant to be used directly. Its primary role is supporting Spring's AOP framework and related core container functionality. We do not use CGLIB's BeanCopier ourselves and therefore only support it on a best-effort basis.

jhoeller avatar Oct 15 '23 13:10 jhoeller

@jhoeller This is very good, looking forward to the official release of this version!

funky-eyes avatar Oct 15 '23 13:10 funky-eyes

This is available in the latest 6.0.14 snapshot now and will be available in the upcoming 5.3.31 snapshot in a few minutes (which can be obtained from repo.spring.io). Please give either of those a try ahead of our release date in November so that we have confidence that the fix works for good now. Alternatively, you could also patch a local Spring Framework setup with the latest org.springframework.cglib.beans.BeanCopier class; it is generally sufficient to just test the latest spring-core.jar for this fix.

jhoeller avatar Oct 15 '23 14:10 jhoeller

It seems this is actually an issue with our context class patch which only works for non-public classes but not for public classes. I got a fix ready to be rolled into 6.0.14, to be backported to 5.3.31 as well.

That said, please note that Spring's repackaged CGLIB fork is not meant to be used directly. Its primary role is supporting Spring's AOP framework and related core container functionality. We do not use CGLIB's BeanCopier ourselves and therefore only support it on a best-effort basis.

yep, spring could consider if that's deleted the cglib's 'BeanCopier' or using another way to support it

SuperEdison avatar Oct 18 '23 06:10 SuperEdison

For the time being, we are trying to make BeanCopier work. If we ever end up in a situation where some CGLIB classes cannot be maintained on recent JDKs anymore, we'd mark them as deprecated... but that does not seem to be necessary yet.

That said, I would appreciate early testing against 6.0.14 / 5.3.31 snapshot builds (from https://repo.spring.io) to verify that BeanCopier actually works for you now, making sure that our November releases are properly resolving this issue.

jhoeller avatar Oct 18 '23 10:10 jhoeller