Monday, 9 July 2012

Realignment for JD-Eclipse

Update: I have posted details about a new release of my plugin here.

In Eclipse, when debugging a Java program or simply trying to explore some code, it is very frustrating when you hit a class without source.



There are a small number of open source Java decompilers which promise to improve this by generating some source code based on the class file. The best one which I have tried is called JD-Eclipse. However, JD-Eclipse has a couple of key limitations:


  1. The generated source code doesn’t line up with the debug line numbers because the generated code can’t include the original comments.
  2. If you choose to associate the “*.class” file type within Eclipse with the “Class File Editor” then you always get decompiled output even if you have real source attached.
I recently came across a project Realignment for JD-Eclipse which partially fixes (1) by properly lining up methods and lines within methods. I have forked this project and made some further enhancements to fix both (1) and (2). In particular, I have added the following:


  • Enhance the re-alignment process to handle enums and fields.
  • Automatically attempt to setup the “correct” file associations.
    • On first start:
      • On Eclipse Juno there is a new “class without source” file type, register to decompile this and restore the built in Class Viewer for classes with source so that attached source can be viewed.
      • On Eclipse Indigo and below register to handle the “class” file type. This can be undone in Window -> Preferences -> General -> Editors -> File Associations.
    • On every other start:
      • If the default “JD Eclipse” editor is registered to handle “class” or “class without source” update the mapping to use the realignment enabled JD Eclipse editor.
  • Add a context menu for choosing which editor to open a class with (see picture below).
  • Add entry to this context menu to allow the attached source to be changed.


If you are interested in trying this out you can download both JD-Eclipse along with my fork of Realignment for JD-Eclipse from my update site: http://mchr3k-eclipse.appspot.com/

Obligatory warning: This code has had very little testing so you please do report any weird behavior to me or raise an issue (https://github.com/mchr3k/jdeclipse-realign/issues).

Implementation Wrinkle

One of the trickiest parts of this project so far has been trying to make it possible to switch quickly between the built in Class Viewer (to view attached source) and the JD Eclipse Class Viewer (to view decompiled source). It turns out that there are two mechanisms which make this tricky when you open a Class in the JD Eclipse Class Viewer.

Firstly the IClassFile is associated with the decompiled source in the BufferManager. With this mapping in place this means that even the built in Class Viewer will display decompiled source. However, the BufferManager is a 60 element LRU cache so if you open enough other files the decompiled source will drop out of the cache.

Secondly the SourceMapper which is used to generate the decompiled source is registered with the IClassFile's parent PackageFragmentRoot. This means that even when the decompiled source is not cached in the BufferManager the built in Class Viewer will still get hold of the cached SourceMapper and generate and then display decompiled source!

To solve both of these issues I added some code to the dispose() method of the Realigned JD Eclipse Class Viewer to both remove the entry from the BufferManager and remove the SourceMapper.

Why does this matter? One of the frustrations with using a decompiler is that once you have one installed you can only view decompiled source even if you have real source attached. I added an "Open Class With" menu to allow a class file to be quickly opened in the regular class viewer to view attached source.

Eclipse Juno makes this much better as it introduces a "class without source" file type so that you can associate your decompiler with only those classes for which you don't have real source.

12 comments:

  1. Awesome! thank you

    https://github.com/ZiglioNZ

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. I'm, getting an error as follows when I try to search and install the updates.. Appreciate your help

    "An error occurred while collecting items to be installed
    session context was:(profile=bootProfile, phase=org.eclipse.equinox.internal.p2.engine.phases.Collect, operand=, action=).
    Artifact not found: osgi.bundle,jd.ide.eclipse,0.1.3.
    http://java.decompiler.free.fr/jd-eclipse/update/plugins/jd.ide.eclipse_0.1.3.jar
    Artifact not found: osgi.bundle,jd.ide.eclipse.win32.x86_64,0.1.3.
    http://java.decompiler.free.fr/jd-eclipse/update/plugins/jd.ide.eclipse.win32.x86_64_0.1.3.jar

    ReplyDelete
    Replies
    1. I ran into the same problem with Indigo.
      I downloaded the following 2 files into my plugins directory, restarted, and the install worked:
      http://pyx4j.com/eclipse/svn/trunk/3.5/plugins/jd.ide.eclipse_0.1.3.jar
      http://pyx4j.com/eclipse/svn/trunk/3.5/plugins/jd.ide.eclipse.win32.x86_64_0.1.3.jar

      good luck

      Delete
    2. Thanks Ken, worked for me! :)

      Delete
  4. Thank you for such an effort of making this better enhanced JADClipse. I had this problems and I know it becomes actually more frustration when you have to deal with decompiled class even when you have the attached source. Before I used to enable and disable this JADClipse. I hope your enhancement saves me from that hassle.

    Thank You!!

    ReplyDelete
  5. Thank you for your kind words :) Just to be clear, my extension is to JD-Eclipse rather than JADClipse.

    ReplyDelete
  6. I used eclipse juno on ubuntu with this plugin.
    For some files it works but for others the whole eclipse crashed with the error:
    # A fatal error has been detected by the Java Runtime Environment:
    #
    # SIGSEGV (0xb) at pc=0x00007f28946635f2, pid=13087, tid=139814477477632
    #
    # JRE version: 6.0_37-b06
    # Java VM: Java HotSpot(TM) 64-Bit Server VM (20.12-b01 mixed mode linux-amd64 compressed oops)
    # Problematic frame:
    # C [libjd-eclipse.so+0xb65f2] SignatureWriter::InternalClassNameToClassName(ReferenceMap&, ClassFile&, wxString&)+0x61
    #
    # An error report file with more information is saved as:
    # /opt/eclipse_with_debuger/hs_err_pid13087.log
    #
    # If you would like to submit a bug report, please visit:
    # http://java.sun.com/webapps/bugreport/crash.jsp
    # The crash happened outside the Java Virtual Machine in native code.
    # See problematic frame for where to report the bug.


    ReplyDelete
    Replies
    1. Any problems with the native library should be reported to it's author: http://java.decompiler.free.fr/?q=jdeclipse

      Delete
  7. Great work ! I tested it recently with Java 7 and i works best of all other realignment plugins for JD (I did try avkosinsky plugin and ootb realignment by JD, they work only sometimes)

    ReplyDelete
  8. very nice work done by you friend !!!!!!

    Just one question, when we decompile a jar by this plugin in eclipse at which place I can find a source for that jar?

    Because when I try to debug source from eclipse it was come to breakpoint and show me blank screen with "Edit Source lookup path" button by using that I can give location of source generated by plugin?

    ReplyDelete