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.