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

CGLIB BeanCopier falls back to ClassLoader.defineClass for public target #28699

Closed
SuperEdison opened this issue Jun 24, 2022 · 26 comments
Closed
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: backported An issue that has been backported to maintenance branches type: bug A general bug
Milestone

Comments

@SuperEdison
Copy link

SuperEdison commented Jun 24, 2022

springframework.version 5.3.21
jdk.version 17

old issue #28530
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

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jun 24, 2022
@livk-cloud
Copy link

livk-cloud commented Jun 27, 2022

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 {

}

@SuperEdison
Copy link
Author

这没有发生任何错误,我尝试使用 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

@livk-cloud
Copy link

livk-cloud commented Jun 27, 2022

这没有发生错误,我试用使用 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

@SuperEdison
Copy link
Author

SuperEdison commented Jun 28, 2022

这没有发生错误,我试用使用 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.

@livk-cloud
Copy link

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

@SuperEdison
Copy link
Author

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 ?

@livk-cloud
Copy link

A类和B类为空

我正在使用 oracle jdk17.0.2

spring 版本之前已经说过了

你能告诉我A类代码吗?

image

image

@SuperEdison
Copy link
Author

SuperEdison commented Jun 28, 2022

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?

@livk-cloud
Copy link

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

@SuperEdison
Copy link
Author

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

@funky-eyes
Copy link
Contributor

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

me too

@mazhewei
Copy link

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.

@invzbl3
Copy link

invzbl3 commented Nov 1, 2022

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

@harryssuperman
Copy link

harryssuperman commented Dec 2, 2022

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.

@ccwxl
Copy link

ccwxl commented Feb 9, 2023

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

@rstoyanchev rstoyanchev added the in: core Issues in core modules (aop, beans, core, context, expression) label Feb 9, 2023
@funky-eyes
Copy link
Contributor

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

@SuperEdison
Copy link
Author

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

@johnny2002
Copy link

Same problem here. add a mark to be notified.

@johnny2002
Copy link

BTW, I am using the latest version spring 6.0.12

@snicoll

This comment was marked as outdated.

@snicoll snicoll closed this as not planned Won't fix, can't repro, duplicate, stale Oct 14, 2023
@snicoll snicoll added for: external-project Needs a fix in external project and removed status: waiting-for-triage An issue we've not yet triaged or decided on in: core Issues in core modules (aop, beans, core, context, expression) labels Oct 14, 2023
@SuperEdison

This comment was marked as off-topic.

@jhoeller
Copy link
Contributor

jhoeller commented Oct 15, 2023

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 jhoeller removed the for: external-project Needs a fix in external project label Oct 15, 2023
@jhoeller jhoeller added type: bug A general bug in: core Issues in core modules (aop, beans, core, context, expression) labels Oct 15, 2023
@jhoeller jhoeller self-assigned this Oct 15, 2023
@jhoeller jhoeller added this to the 6.0.14 milestone Oct 15, 2023
@jhoeller jhoeller changed the title Support for CGLIB BeanCopier utility on JDK 17 still error CGLIB BeanCopier falls back to ClassLoader.defineClass for public target on JDK 17 Oct 15, 2023
@jhoeller jhoeller changed the title CGLIB BeanCopier falls back to ClassLoader.defineClass for public target on JDK 17 CGLIB BeanCopier falls back to ClassLoader.defineClass for public target Oct 15, 2023
@funky-eyes
Copy link
Contributor

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

@github-actions github-actions bot added the status: backported An issue that has been backported to maintenance branches label Oct 15, 2023
@jhoeller jhoeller reopened this Oct 15, 2023
jhoeller added a commit that referenced this issue Oct 15, 2023
Includes consistent formatting of Spring-patched files.

Closes gh-28699

(cherry picked from commit 7a60e20)
@jhoeller
Copy link
Contributor

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.

@sbrannen sbrannen changed the title CGLIB BeanCopier falls back to ClassLoader.defineClass for public target CGLIB BeanCopier falls back to ClassLoader.defineClass for public target Oct 15, 2023
@SuperEdison
Copy link
Author

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

@jhoeller
Copy link
Contributor

jhoeller commented Oct 18, 2023

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: backported An issue that has been backported to maintenance branches type: bug A general bug
Projects
None yet
Development

No branches or pull requests