judovana / java-runtime-decompiler

GNU General Public License v3.0
68 stars 14 forks source link

Provide feedback from getClass when class is not found (not throw `RuntimeException`) #199

Closed mkoncek closed 2 years ago

mkoncek commented 2 years ago

(CFR decompiler)

Processing com.google.gson.JsonPrimitive
java.lang.RuntimeException: Class com.google.gson.internal. not found in loaded classes.
        at org.jrd.agent.InstrumentationProvider.findClass(InstrumentationProvider.java:80)
        at org.jrd.agent.InstrumentationProvider.findClassBody(InstrumentationProvider.java:69)
        at org.jrd.agent.AgentActionWorker.sendByteCode(AgentActionWorker.java:193)
        at org.jrd.agent.AgentActionWorker.executeRequest(AgentActionWorker.java:107)
        at org.jrd.agent.AgentActionWorker.<init>(AgentActionWorker.java:41)
        at org.jrd.agent.ConnectionDelegator.run(ConnectionDelegator.java:78)
java.lang.RuntimeException: Agent returned error: java.lang.RuntimeException: Class com.google.gson.internal. not found in loaded classes.
        at org.jrd.backend.communication.Communicate.readResponse(Communicate.java:117)
        at org.jrd.backend.communication.CallDecompilerAgent.submitRequest(CallDecompilerAgent.java:48)
        at org.jrd.backend.core.DecompilerRequestReceiver.getResponse(DecompilerRequestReceiver.java:144)
        at org.jrd.backend.core.DecompilerRequestReceiver.getByteCodeAction(DecompilerRequestReceiver.java:197)
        at org.jrd.backend.core.DecompilerRequestReceiver.processRequest(DecompilerRequestReceiver.java:77)
        at org.jrd.frontend.frame.main.DecompilationController.submitRequest(DecompilationController.java:570)
        at org.jrd.backend.data.Cli.obtainClass(Cli.java:796)
        at org.jrd.backend.communication.RuntimeCompilerConnector$JrdClassesProvider.getClass(RuntimeCompilerConnector.java:44)
        at io.github.mkoncek.classpathless.impl.CompilerJavac.transitiveImport(CompilerJavac.java:123)
        at io.github.mkoncek.classpathless.impl.CompilerJavac.compileClass(CompilerJavac.java:151)
...

The problem is with the class $Gson$Preconditions, someone thought it would be a good idea to use $ in a normal class name. Nevertheless it is completely legal to name your class with dollars. Problem then is, i have no way of knowing whether it actually is a nested class or not, i can only find out by requesting getClass from JRD. However if you don't find a class with the prefixed name, you end up throwing a generic RuntimeException. I think it would be better to simply return an empty collection (or throw a more specific exception).

AurumTheEnd commented 2 years ago

The problem is with the class $Gson$Preconditions, someone thought it would be a good idea to use $ in a normal class name. Nevertheless it is completely legal to name your class with dollars.

What an interesting edge case! Will fix.

AurumTheEnd commented 2 years ago

(CFR decompiler)

More broadly speaking it is any decompiler wrapper implementing the decompileWithInners(...) method, probably.

AurumTheEnd commented 2 years ago

@mkoncek, looking into it, I have no problem decompiling $Gson$Preconditions with CFR, not even with CFR_old before 09a8933 fixing #96. What class were you trying to decompile? What is the version of Cfr.jar in your Cfr decompiler wrapper plugin? (Configure -> Plugins)

mkoncek commented 2 years ago

It was there before you edited it: Processing com.google.gson.JsonPrimitive. It imports $Gson$Preconditions.

AurumTheEnd commented 2 years ago

Oops, misclicked on that one, my bad.

mkoncek commented 2 years ago

This probably also needs slight adjustments on CPLC side, but in order to play around with it I first need JRD not to crash. (Although maybe i can just catch the exception)

mkoncek commented 2 years ago

Can confirm that catching RuntimeException on my side makes the file compile, but that is just an observation, not a solution.

AurumTheEnd commented 2 years ago

image

image

image

Need more info to replicate the bug. With the latest CFR jar, CFR wrapper and JRD, I have no issue decompiling $Gson$Precondition nor JsonPrimitive in both CLI and GUI. (it is not lazy-loaded on startup)

Note that the PIDs of the target processes are different every time to not cross-contaminate.

mkoncek commented 2 years ago

https://github.com/pmikova/java-runtime-decompiler/pull/205 has probably fixed this, but it still floods stderr. Although i don't think yoou can do much about it.

AurumTheEnd commented 2 years ago

Expanded stderr messages in #206 to be more explanatory.

However because the error logging happens much deeper than in either JrdClassesProvider or Cli::obtainClass/Cli::initClass, we cannot outright remove the log calls.

One option would be to temporarily switch System.err with a dummy PrintStream, but that's worth considering in another issue. This one will close with #206.