6

I am running JUnit case with PowerMock in jdk7 using the below libraries :

cglib-nodep-2.2.2.jar
javassist-3.19.0-GA.jar
junit-4.12.jar
mockito-all-1.10.19.jar
objenesis-2.1.jar
powermock-mockito-1.6.2-full.jar

Below is code snippet from my Unit Test in which I am using PowerMock

@RunWith(PowerMockRunner.class)
@PrepareForTest(ValidateBindingImpl.class)
public class ValidateBindingImplTest{

//more code follows
}

While executing this test case I am getting following error:

java.lang.ClassFormatError: Invalid method Code length 119842 in class file com/v1/ValidateBindingImpl
    at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
at java.lang.ClassLoader.defineClass(ClassLoader.java:465)
at org.powermock.core.classloader.MockClassLoader.loadMockClass(MockClassLoader.java:269)
at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:180)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:68)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:249)
at sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:95)
at sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:107)
at sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:31)
at sun.reflect.annotation.AnnotationParser.parseSig(AnnotationParser.java:370)
at sun.reflect.annotation.AnnotationParser.parseClassValue(AnnotationParser.java:351)
at sun.reflect.annotation.AnnotationParser.parseClassArray(AnnotationParser.java:653)
at sun.reflect.annotation.AnnotationParser.parseArray(AnnotationParser.java:460)
at sun.reflect.annotation.AnnotationParser.parseMemberValue(AnnotationParser.java:286)
at sun.reflect.annotation.AnnotationParser.parseAnnotation(AnnotationParser.java:222)
at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:69)
at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:52)
at java.lang.Class.initAnnotationsIfNecessary(Class.java:3079)
at java.lang.Class.getAnnotation(Class.java:3038)
at org.junit.internal.MethodSorter.getDeclaredMethods(MethodSorter.java:52)
at org.junit.internal.runners.TestClass.getAnnotatedMethods(TestClass.java:45)
at org.junit.internal.runners.MethodValidator.validateTestMethods(MethodValidator.java:71)
at org.junit.internal.runners.MethodValidator.validateStaticMethods(MethodValidator.java:44)
at org.junit.internal.runners.MethodValidator.validateMethodsForDefaultRunner(MethodValidator.java:50)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.validate(PowerMockJUnit44RunnerDelegateImpl.java:108)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.<init>(PowerMockJUnit44RunnerDelegateImpl.java:70)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl.<init>(PowerMockJUnit47RunnerDelegateImpl.java:42)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit49RunnerDelegateImpl.<init>(PowerMockJUnit49RunnerDelegateImpl.java:25)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:156)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:40)
at org.powermock.tests.utils.impl.AbstractTestSuiteChunkerImpl.createTestDelegators(AbstractTestSuiteChunkerImpl.java:244)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.<init>(JUnit4TestSuiteChunkerImpl.java:61)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.<init>(AbstractCommonPowerMockRunner.java:32)
at org.powermock.modules.junit4.PowerMockRunner.<init>(PowerMockRunner.java:34)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:29)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:21)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:26)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.<init>(JUnit4TestReference.java:33)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestClassReference.<init>(JUnit4TestClassReference.java:25)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:48)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:444)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Found similar post discussed here and here based on which I tried adding -XX:-UseSplitVerifier in VM arguments but it didn't work.

Moreover I understand that the error seem to occur due to lengthy method in my class file but as its my organization code I wont be able modify/split the method as suggested in some posts online.

Community
  • 1
  • 1
Ash
  • 103
  • 2
  • 2
  • 7

4 Answers4

7

You faced with the following issue: JVM has limit on method size in bites, but during byte code transformation which is required to make possible mocking static, final size of the method could exceed this limit. In this case you see this error

java.lang.ClassFormatError: Invalid method Code length 119842 in class file

In next release will be include fix, which addressed this issue by replacing huge method via code which throws exception by default, but you still able to suppress such, method.

But, it's still will be only workaround for classes you cannot modified. Right way to fix the issue, it's to refactor your code to make method smaller. There are a lot of refactoring techniques to achieve this goal.

Artur Zagretdinov
  • 2,034
  • 13
  • 22
2

You will probably not like my answer, but the only reasonable answer is: stop using PowerMock.

If your production code is such that you need PowerMock in order write unit tests; then seriously: change your production code. If you need PowerMock, then your "code under test" is most likely: bad.

PowerMock (and all other mocking frameworks that rely on byte code manipulation) most often, cause more trouble than good. They cause issues like the one you got now; they very much limit your ability to use different JVMs or to run coverage tools.

This comes from a person who spent countless hours fixing "PowerMock" based unit tests; and who has written hundreds of unit tests over the last months only relying on EasyMock; and not once had the need to turn to PowerMock.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • @GhostCat Is is possible to test private methods, static stuff using EasyMock? – ikos23 Feb 12 '18 at 13:51
  • @john A) you don't **test** private methods - they contain implementation details, you test **public** methods B) of course you can **test** static methods ... but I guess you meant to say "can I *mock* private / static methods using EasyMock?" and the answer to that is: no, you can't – GhostCat Feb 12 '18 at 13:59
  • @GhostCat sorry for not being clear. yes, in particular, can you mock them? If you have some specific algorithm that is being used several times in the same class, does it make sense to impl it as a private method and use in several public methods? And your public methods might do much more than just call that private method and the algorithm you coded contains some logic that you would like to test to verify it produces correct result, what would you do ? – ikos23 Feb 12 '18 at 14:34
  • @john If your algorithm is such a central piece for your code ... then it probably deserves its own *class*. In other words: read the clean code book by Robert Martin. Your questions imply that you are lacking knowledge how to reasonably structure your source code ;-) – GhostCat Feb 12 '18 at 14:36
  • @GhostCat I couldn't agree more. I will ) – ikos23 Feb 12 '18 at 15:47
1

To use JVM option '-noverify': https://bugs.eclipse.org/bugs/show_bug.cgi?id=435446

Do Tat Hoan
  • 901
  • 9
  • 9
  • In my case, this issue related to javassist verison and I reported in thread "Error mocking Class which hold reference to SQLiteOpenHelper": https://stackoverflow.com/questions/47768644/error-mocking-class-which-hold-reference-to-sqliteopenhelper/53759201#53759201 – Do Tat Hoan Aug 11 '19 at 21:08
  • That would just make the JVM crash instead of throwing an exception. – JRA_TLL Nov 21 '19 at 12:45
0

As mentioned earlier, this can happen not just by trying to instrument a large method, but also trying to instrument a class with a large number of methods.

I've encountered a break at around +/- 1500 methods. It depends on the methods signatures in the class.

Try to reduce the number of methods in the class.

Gufran Hasan
  • 8,910
  • 7
  • 38
  • 51
  • It is not the number of methods, but every method may not be larger than 64KB. One is 119842 Bytes according to the errror msg. – JRA_TLL Nov 21 '19 at 12:46