-
Notifications
You must be signed in to change notification settings - Fork 227
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
java.lang.NoClassDefFoundError: java/lang/ReflectiveOperationException #104
Comments
There is no easy way to backport a library which uses Java 7/8 APIs. The ReflectiveOperationException error is probably a case of the code in that library catching it or using it in a throws clause. The library would need to be changed to not catch that exception, but those of its subclasses which exist on Java 6. Usages of other new APIs need to be changed in a case by case manner. You would probably have to fork that library and manually change all of its code to avoid Java 7/8 APIs. IntelliJ IDEA has a code inspection for warning about usages of too new APIs. And/or run its tests under Java 6 and see where it fails. |
I steped into the same problem and realized that I was using a multi-catch block like: try {
... //stuff
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ignore) {
} After expanding the multi-catch block to: try {
... //stuff
} catch (NoSuchMethodException ignore) {
} catch (InvocationTargetException ignore) {
} catch (IllegalAccessException ignore) {
} In the case of the multi-catch statement, looking at the bytecode one can see that there is a frame that refers FRAME SAME1 java/lang/ReflectiveOperationException
ASTORE 0 vs FRAME SAME1 java/lang/NoSuchMethodException
ASTORE 0
... //other instructions
FRAME SAME1 java/lang/reflect/InvocationTargetException
ASTORE 0
... //other instructions
FRAME SAME1 java/lang/IllegalAccessException
ASTORE 0 It is wise to avoid multi-catch statements when dealing with lambda's, to avoid such issues at runtime. |
That multi-catch optimization done by javac is interesting. Maybe it would be possible to duplicate the catch block and replace it with catch blocks for the individual exceptions. Sounds like a lot of work, so I won't try doing it right now. Pull requests are welcome. |
I was about to write my idea few minutes ago. What I can do is to build a script to build a list of newly added type of exceptions in the middle of the existing hierarchy for java 8 and see if they have any special methods or not and create a list. I think the number of added exceptions is small and translation map can be used. Let me know if you want to go forward with this idea or any other suggestion and I can help. As a side note, even if I am using this library for educational purposes, it is a great one. I learned a lot from analyzing what it does and how it goes. Great work! In case anyone else is looking, here is how the TRYCATCHBLOCK L0 L1 L2 java/lang/NoSuchMethodException
TRYCATCHBLOCK L0 L1 L2 java/lang/IllegalAccessException
TRYCATCHBLOCK L0 L1 L2 java/lang/reflect/InvocationTargetException |
Duplicating that try catch block seem to be more consistent than my idea of translating the exception to the super type, as it inlines better with the substitution principle. I am not sure how easy is to achieve that. |
I haven't checked the code, but duplicating the catch block shouldn't be too hard. It should be either just copying the bytecode instructions as-is, or maybe just modifying the trycatch table or adding a few gotos is enough. It would be risky to change the code to catch the next superclass, because that will change code semantics. |
When java 8 code uses reflection the class ReflectiveOperationException doesn't get backported to java 6. Causing a NoClassDefFoundError because all reflection exceptions derive from it since java 7. Would it be possible to add support for it?
I'm asking because I want to backport https://github.com/sdaschner/jaxrs-analyzer to java 6. Because this failed I tried to convert it to java 7, but this gave other NoClassDefFoundErrors. So actually my question is, could you enhance retrolambda to support this project?
Or what would be required to facilitate that enhancment, is there an easy way to say "backport these core java classes that are unavailable in java 6"?
The text was updated successfully, but these errors were encountered: