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

Internal APIs stricter access on Java11 require unit tests and example change #2

Closed
NingZhang-e opened this issue Nov 2, 2018 · 4 comments

Comments

@NingZhang-e
Copy link
Contributor

Change javassist version to 3.24.0-GA which support Java11 and switch to JDK11 to build this project.
Many unit tests will fail, like DelegateProxyTest.createNewProxyClass():

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access using Lookup on javassist.util.proxy.DefineClassHelper (file:/C:/Opensource/javassist/target/classes/) to class java.util.ArrayList
WARNING: Please consider reporting this to the maintainers of javassist.util.proxy.DefineClassHelper
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
FAILED: createNewProxyClass
com.ericsson.commonlibrary.proxy.ProxyException: Not able to create proxy
	at com.ericsson.commonlibrary.proxy.InterceptableProxyFactory.build(InterceptableProxyFactory.java:92)
	at com.ericsson.commonlibrary.proxy.InterceptableProxyFactory.createANewClassProxy(InterceptableProxyFactory.java:317)
	at com.ericsson.commonlibrary.proxy.Proxy.delegateClass(Proxy.java:73)
	at com.ericsson.commonlibrary.proxy.Proxy.delegate(Proxy.java:69)
	at com.ericsson.commonlibrary.proxy.DelegateProxyTest.createNewProxyClass(DelegateProxyTest.java:213)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:124)
	at org.testng.internal.Invoker.invokeMethod(Invoker.java:580)
	at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:716)
	at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:988)
	at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
	at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
	at org.testng.TestRunner.privateRun(TestRunner.java:648)
	at org.testng.TestRunner.run(TestRunner.java:505)
	at org.testng.SuiteRunner.runTest(SuiteRunner.java:455)
	at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450)
	at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415)
	at org.testng.SuiteRunner.run(SuiteRunner.java:364)
	at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
	at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84)
	at org.testng.TestNG.runSuitesSequentially(TestNG.java:1208)
	at org.testng.TestNG.runSuitesLocally(TestNG.java:1137)
	at org.testng.TestNG.runSuites(TestNG.java:1049)
	at org.testng.TestNG.run(TestNG.java:1017)
	at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:114)
	at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251)
	at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)
Caused by: java.lang.RuntimeException: Class not in same package as lookup class: java.util.ArrayList has no permission to define the class
	at javassist.util.proxy.ProxyFactory.createClass3(ProxyFactory.java:614)
	at javassist.util.proxy.ProxyFactory.createClass2(ProxyFactory.java:587)
	at javassist.util.proxy.ProxyFactory.createClass1(ProxyFactory.java:523)
	at javassist.util.proxy.ProxyFactory.createClass(ProxyFactory.java:449)
	at javassist.util.proxy.ProxyFactory.create(ProxyFactory.java:789)
	at javassist.util.proxy.ProxyFactory.create(ProxyFactory.java:774)
	at com.ericsson.commonlibrary.proxy.InterceptableProxyFactory.createProxyObject(InterceptableProxyFactory.java:237)
	at com.ericsson.commonlibrary.proxy.InterceptableProxyFactory.build(InterceptableProxyFactory.java:90)
	... 29 more
Caused by: javassist.CannotCompileException: Class not in same package as lookup class: java.util.ArrayList has no permission to define the class
	at javassist.util.proxy.DefineClassHelper.toClass(DefineClassHelper.java:300)
	at javassist.util.proxy.DefineClassHelper$Java11.defineClass(DefineClassHelper.java:48)
	at javassist.util.proxy.DefineClassHelper.toClass(DefineClassHelper.java:263)
	at javassist.util.proxy.FactoryHelper.toClass(FactoryHelper.java:136)
	at javassist.util.proxy.ProxyFactory.createClass3(ProxyFactory.java:603)
	... 36 more

Because unit test is executed on ArrayList which is Java internal class, the error happened.
I created one unit test towards javassist directly:

public void testJava11() throws Exception {
    	ProxyFactory factory = new ProxyFactory();
        factory.setSuperclass(HashMap.class);
        
        HashMap e = (HashMap)factory.create(null, null, new MethodHandler() {
            @Override
            public Object invoke(Object self, Method thisMethod,
                    Method proceed, Object[] args) throws Throwable {
                return proceed.invoke(self, args);
            }
        });
    }

Same error will happen. If changing HashMap to one customized new class, there is no such issue.
Here is one article to describe the possible reason:
https://blog.codefx.org/java/java-11-migration-guide/#Illegal-Access-To-Internal-APIs

@NingZhang-e
Copy link
Contributor Author

Post this issue on javassist page:

jboss-javassist/javassist#228

@NingZhang-e
Copy link
Contributor Author

NingZhang-e commented Dec 3, 2018

I just tried some workaround to bypass Java11 issue: create one temp class extend Java built-in class, then create proxy of this created temp class.
Something like below in InterceptableProxyFactory.java#L315

if ("java.util".equals(classToIntercept.getPackageName())) {
        ClassPool pool = ClassPool.getDefault();
        CtClass cc = pool.makeClass("com.ericsson.commonlibrary.proxy." + classToIntercept.getName());
        try {
	       cc.setSuperclass(pool.get(classToIntercept.getName()));
		builder.setSuperclass(cc.toClass());
	} catch (CannotCompileException | NotFoundException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}        	
} else {
        builder.setSuperclass(classToIntercept);
 }

It works well.
I will seek fix to all similar issues.

@NingZhang-e
Copy link
Contributor Author

Someone else fixed the issue in their own project:
jboss-javassist/javassist#228 (comment)

@NingZhang-e
Copy link
Contributor Author

There is already one fix for this issue. Then we could wait for new release of javassist, then update pom and deliver a new release.

NingZhang-e added a commit that referenced this issue Jan 4, 2019
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

1 participant