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

Introduce public defineClass variant for SmartClassLoader implementations #26403

Closed
jhoeller opened this issue Jan 19, 2021 · 0 comments
Closed
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@jhoeller
Copy link
Contributor

jhoeller commented Jan 19, 2021

Considering some scenarios raised in #22814, it seems that Boot's RestartClassLoader is commonly the target of a newly defined proxy class there, with the original class living in the system class loader (either because of early loading or simply because it is a JDK library class). In such a scenario, we have to fall back to a ClassLoader-specific defineClass call - which we traditionally do through a reflective call to the protected defineClass method, triggering an illegal access warning on JDK 9+ (and not working at all anymore with illegal access being denied, forcing us to fall back to defining the proxy class in the same class loader as the original class, i.e. the system class loader, since this is the only thing JDK 9's ´Lookup.defineClass` can do).

While we cannot generally solve the problem for arbitrary nested class loader scenarios, we can introduce a public hook for class loader implementations that we control. By extending the SmartClassLoader interface to not only identify reloadable classes (its traditional purpose) but to also allow for flexible class definitions through a new publicDefineClass method, Boot's RestartClassLoader can implement it with a simple delegation to its ClassLoader-inherited protected defineClass method:

	@Override
	public Class<?> publicDefineClass(String name, byte[] b, @Nullable ProtectionDomain protectionDomain) {
		return defineClass(name, b, 0, b.length, protectionDomain);
	}

Since we cannot detect the SmartClassLoader interface at the CGLIB implementation level (for dependency reasons), we could instead simply detect the publicDefineClass method by convention in CGLIB's ReflectUtils. Any ClassLoader implementation with such a method signature can therefore comply with that convention, without introducing a dependency on spring-core.

@jhoeller jhoeller added in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement labels Jan 19, 2021
@jhoeller jhoeller added this to the 5.3.4 milestone Jan 19, 2021
@jhoeller jhoeller self-assigned this Jan 19, 2021
snicoll added a commit to snicoll/spring-boot that referenced this issue Jan 19, 2021
This commit improves RestartClassLoader to use a method introduced in
SmartClassLoader to avoid triggering a warning on Java 11 and later.

See spring-projects/spring-framework#26403

Closes spring-projectsgh-24857
snicoll added a commit to spring-projects/spring-boot that referenced this issue Feb 11, 2021
This commit improves RestartClassLoader to use a method introduced in
SmartClassLoader to avoid triggering a warning on Java 11 and later.

See spring-projects/spring-framework#26403

Closes gh-24857
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) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

1 participant