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

Javassist incompatible with Mockito/Junit4.Result in Java 11 (due to IllegalAccess to Unsafe?) #227

Open
remibarat opened this issue Oct 31, 2018 · 6 comments

Comments

@remibarat
Copy link

Versions:

  • Javassist 3.23.1-GA (also tested with 3.24.0-RC)
  • Mockito 2.23.0
  • Junit 4.12
  • Java 11.0.0 (openjdk)

When I try to invoke a method that either creates a Mockito.mock or a junit.runner.Result through Javassist, it does not work anymore when running with Java 11.

This is surely because we have not access to Unsafe (see with basicTest3). I have tried to run with add-opens java.base/jdk.internal.misc and add-opens java.base/jdk.internal.reflect, without success.

A simple example on how to reproduce the errors:

public void testSimpleInjection() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException
{
	ClassPool classPool = ClassPool.getDefault();
	Loader loader = new Loader(classPool);
	Class<?> clazz = loader.loadClass(this.getClass.getName());
	Method method = clazz.getMethod("basicTest");
	method.invoke(null);
}

public static void basicTest() { Mockito.mock(Object.class); }
public static void basicTest2() { new Result(); } // org.junit.runner.Result
public static void basicTest3() { jdk.internal.misc.getUnsafe(); } // even if --add-exports/add-opens java.base/jdk.internal.misc is provided

StackTraces:

  • basicTest
java.lang.reflect.InvocationTargetException
	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 com.qfs.memory.impl.TestCodeInjectionUtil.testSimpleInjectionWithMock(TestCodeInjectionUtil.java:151)
	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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.IllegalStateException: Could not initialize plugin: interface org.mockito.plugins.MockMaker (alternate: null)
	at org.mockito.internal.configuration.plugins.PluginLoader$1.invoke(PluginLoader.java:74)
	at com.sun.proxy.$Proxy8.isTypeMockable(Unknown Source)
	at org.mockito.internal.util.MockUtil.typeMockabilityOf(MockUtil.java:29)
	at org.mockito.internal.util.MockCreationValidator.validateType(MockCreationValidator.java:22)
	at org.mockito.internal.creation.MockSettingsImpl.validatedSettings(MockSettingsImpl.java:238)
	at org.mockito.internal.creation.MockSettingsImpl.build(MockSettingsImpl.java:226)
	at org.mockito.internal.MockitoCore.mock(MockitoCore.java:68)
	at org.mockito.Mockito.mock(Mockito.java:1895)
	at org.mockito.Mockito.mock(Mockito.java:1804)
	at com.qfs.memory.impl.TestCodeInjectionUtil.basicTestForInjectionWithMock(TestCodeInjectionUtil.java:136)
	... 27 more
Caused by: java.lang.UnsatisfiedLinkError: jdk.internal.misc.Unsafe.registerNatives()V
	at jdk.internal.misc.Unsafe.registerNatives(Native Method)
	at jdk.internal.misc.Unsafe.<clinit>(Unsafe.java:57)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:315)
	at net.bytebuddy.dynamic.loading.ClassInjector$UsingUnsafe$Dispatcher$CreationAction.run(ClassInjector.java:1892)
	at net.bytebuddy.dynamic.loading.ClassInjector$UsingUnsafe$Dispatcher$CreationAction.run(ClassInjector.java:1839)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at net.bytebuddy.dynamic.loading.ClassInjector$UsingUnsafe.<clinit>(ClassInjector.java:1697)
	at net.bytebuddy.dynamic.loading.ClassInjector$UsingReflection$Dispatcher$CreationAction.run(ClassInjector.java:439)
	at net.bytebuddy.dynamic.loading.ClassInjector$UsingReflection$Dispatcher$CreationAction.run(ClassInjector.java:425)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at net.bytebuddy.dynamic.loading.ClassInjector$UsingReflection.<clinit>(ClassInjector.java:114)
	at org.mockito.internal.creation.bytebuddy.SubclassInjectionLoader.<init>(SubclassInjectionLoader.java:28)
	at org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker.<init>(SubclassByteBuddyMockMaker.java:33)
	at org.mockito.internal.creation.bytebuddy.ByteBuddyMockMaker.<init>(ByteBuddyMockMaker.java:21)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at java.base/java.lang.Class.newInstance(Class.java:584)
	at org.mockito.internal.configuration.plugins.DefaultMockitoPlugins.create(DefaultMockitoPlugins.java:66)
	at org.mockito.internal.configuration.plugins.DefaultMockitoPlugins.getDefaultPlugin(DefaultMockitoPlugins.java:43)
	at org.mockito.internal.configuration.plugins.PluginLoader.loadPlugin(PluginLoader.java:67)
	at org.mockito.internal.configuration.plugins.PluginLoader.loadPlugin(PluginLoader.java:44)
	at org.mockito.internal.configuration.plugins.PluginRegistry.<init>(PluginRegistry.java:21)
	at org.mockito.internal.configuration.plugins.Plugins.<clinit>(Plugins.java:18)
	at org.mockito.internal.util.MockUtil.<clinit>(MockUtil.java:24)
	... 34 more
  • basicTest2
java.lang.reflect.InvocationTargetException
	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 com.qfs.memory.impl.TestCodeInjectionUtil.testSimpleInjectionWithResult(TestCodeInjectionUtil.java:132)
	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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.IllegalAccessError: class jdk.internal.reflect.ConstructorAccessorImpl loaded by javassist.Loader @4b9e255 cannot access jdk/internal/reflect superclass jdk.internal.reflect.MagicAccessorImpl
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:877)
	at javassist.Loader.findClass(Loader.java:377)
	at javassist.Loader.loadClass(Loader.java:308)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:877)
	at javassist.Loader.findClass(Loader.java:377)
	at javassist.Loader.loadClass(Loader.java:308)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	at java.base/jdk.internal.misc.Unsafe.defineClass0(Native Method)
	at java.base/jdk.internal.misc.Unsafe.defineClass(Unsafe.java:1192)
	at java.base/jdk.internal.reflect.ClassDefiner.defineClass(ClassDefiner.java:63)
	at java.base/jdk.internal.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:400)
	at java.base/jdk.internal.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:394)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/jdk.internal.reflect.MethodAccessorGenerator.generate(MethodAccessorGenerator.java:393)
	at java.base/jdk.internal.reflect.MethodAccessorGenerator.generateSerializationConstructor(MethodAccessorGenerator.java:112)
	at java.base/jdk.internal.reflect.ReflectionFactory.generateConstructor(ReflectionFactory.java:514)
	at java.base/jdk.internal.reflect.ReflectionFactory.newConstructorForSerialization(ReflectionFactory.java:506)
	at java.base/java.io.ObjectStreamClass.getSerializableConstructor(ObjectStreamClass.java:1516)
	at java.base/java.io.ObjectStreamClass$2.run(ObjectStreamClass.java:509)
	at java.base/java.io.ObjectStreamClass$2.run(ObjectStreamClass.java:484)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.io.ObjectStreamClass.<init>(ObjectStreamClass.java:484)
	at java.base/java.io.ObjectStreamClass.lookup(ObjectStreamClass.java:381)
	at java.base/java.io.ObjectStreamClass.lookup(ObjectStreamClass.java:225)
	at org.junit.runner.Result.<clinit>(Result.java:27)
	at com.qfs.memory.impl.TestCodeInjectionUtil.basicTestForInjectionWithResult(TestCodeInjectionUtil.java:118)
	... 27 more
  • basicTest3
java.lang.reflect.InvocationTargetException
	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 com.qfs.memory.impl.TestCodeInjectionUtil.testSimpleInjectionWithMock(TestCodeInjectionUtil.java:154)
	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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.UnsatisfiedLinkError: jdk.internal.misc.Unsafe.registerNatives()V
	at jdk.internal.misc.Unsafe.registerNatives(Native Method)
	at jdk.internal.misc.Unsafe.<clinit>(Unsafe.java:57)
	at com.qfs.memory.impl.TestCodeInjectionUtil.basicTestForInjectionWithMock(TestCodeInjectionUtil.java:137)
@chibash
Copy link
Member

chibash commented Nov 1, 2018

Is this really a problem of Javassist? I cannot see javassist in basicTest or basicTest3.

@remibarat
Copy link
Author

Regarding basicTest and basicTest3, I am currently investigating what is the real cause of the issue. I just noticed in Java 8, basicTest also throws, and basicTest3 does not have sense.

@remibarat
Copy link
Author

basicTest works in Java 8 if I add Thread.currentThread.setContextClassLoader(loader) before invoking the method. But it still fails in Java 11 with the same stack trace.

@remibarat
Copy link
Author

remibarat commented Nov 6, 2018

I found a workaround so that basicTest and basicTest2 pass. I need to add

loader.delegateLoadingOf("jdk.internal.misc.Unsafe"); // needed for Mockito#mock
loader.delegateLoadingOf("jdk.internal.reflect.MethodAccessorImpl"); // needed for Mockito#mock
loader.delegateLoadingOf("jdk.internal.reflect.SerializationConstructorAccessorImpl"); // needed for Mockito#mock & Junit4#Result

Is it something normal? Is there a way to avoid this workaround?

@richbolen
Copy link

Another issue with Java 11 is they added a new constant 17 CONSTANT_Dynamic. When will javassist support this constant?

@chibash
Copy link
Member

chibash commented Aug 15, 2019

See issue #270

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

3 participants