Decompiling and Recompiling Java Packages

Posted Thursday, 04 March 2010 at 02:03 by Andrew Liu
Tagged: java | web development | xml soap
Read more blogs...


I came across the need to decompile a java package from an existing application, having to recode a small portion of it.  This all sounded ok, but I wasn't sure about the recompiling of the package and putting the new package back into the application.  It sounded normal, but it was quite a large application and, moreover, it was windows based!  So I googled around to see if people had done this before - it sounds doable, but there were no real "this is how you do it" instructions.


So here is a brief run through.  ** WARNING ** this is by no means a "this is how you do it" set of instructions, as every scenario is different.  You will have to improvise as best you can, and use logic to substitute your values in where possible.  I will use an example below instead of a "one instruction fits all" approach, and highlight potential errors on the way.


1. Extract the JAR file


Firstly, I had to pull apart the JAR file.  JAR files are simply ZIP files with a bit more information about the contents (contained in the META-INF).  Most linux systems with Java will have a command line available called 'jar', which is similar to the 'tar' command.  In my particular scenario, I was extracting the contents of a file called 'sas.portal.jar'.


$ mkdir sas.portal
$ cd sas.portal
$ jar xvf ../sas.portal.jar
$ ls -al
total 32
drwxr-xr-x  4 root root 4096 2009-03-24 11:17 .
drwx------ 34 aliu aliu 4096 2009-03-24 11:17 ..
-rw-r--r--  1 root root   94 2007-07-19 10:58 buildinfo.txt
drwxr-xr-x  3 root root 4096 2007-07-19 10:57 com
-rw-r--r--  1 root root  438 2007-07-19 10:58 disposers.config
drwxr-xr-x  3 root root 4096 2009-03-24 11:21 META-INF
-rw-r--r--  1 root root 5161 2007-07-19 10:58 portlet.dtd


If we dig into the 'com' directory, we will find the class files within.


$ ls -al com
total 12
drwxr-xr-x 3 root root 4096 2007-07-19 10:57 .
drwxr-xr-x 4 root root 4096 2009-03-24 11:17 ..
drwxr-xr-x 4 root root 4096 2007-07-19 10:57 sas
$ ls -al com/sas
total 16
drwxr-xr-x  4 root root 4096 2007-07-19 10:57 .
drwxr-xr-x  3 root root 4096 2007-07-19 10:57 ..
drwxr-xr-x  3 root root 4096 2007-07-19 10:57 apps
drwxr-xr-x 20 root root 4096 2007-07-19 10:58 portal
$ ls -al com/sas/portal
total 152
drwxr-xr-x 20 root root  4096 2007-07-19 10:58 .
drwxr-xr-x  4 root root  4096 2007-07-19 10:57 ..
drwxr-xr-x  3 root root 12288 2007-07-19 10:57 actions
drwxr-xr-x  3 root root  4096 2007-07-19 10:57 app
drwxr-xr-x  6 root root  4096 2007-07-19 10:57 container
drwxr-xr-x 13 root root  4096 2007-07-19 10:57 delegates
drwxr-xr-x  2 root root  4096 2007-07-19 10:57 dynamicResources
drwxr-xr-x  2 root root  4096 2007-07-19 10:57 filters
drwxr-xr-x  2 root root  4096 2007-07-19 10:57 httpfilters
drwxr-xr-x  3 root root  4096 2007-07-19 10:57 lifecycle
-rw-r--r--  1 root root 12695 2007-07-19 10:57 Logger.class
drwxr-xr-x  2 root root  4096 2007-07-19 10:57 metadatadeploy
drwxr-xr-x  2 root root  4096 2007-07-19 10:57 mgmt
drwxr-xr-x  3 root root  4096 2007-07-19 10:57 model
-rw-r--r--  1 root root   886 2007-07-19 10:57 ObjectNotFoundException.class
-rw-r--r--  1 root root  6629 2007-07-19 10:57 PortalCommonStrings.class
-rw-r--r--  1 root root  5758 2007-07-19 10:57 PortalContext.class
-rw-r--r--  1 root root  1072 2007-07-19 10:57 PortalContextInterface.class
-rw-r--r--  1 root root   862 2007-07-19 10:57 PortalException.class
-rw-r--r--  1 root root 10947 2007-07-19 10:57 PortalFactory.class
-rw-r--r--  1 root root   294 2007-07-19 10:57 PortalGlobals.class
-rw-r--r--  1 root root  2987 2007-07-19 10:57 PortalResources.class
drwxr-xr-x  3 root root  4096 2007-07-19 10:57 portlet
drwxr-xr-x  4 root root  4096 2007-07-19 10:57 portlets
drwxr-xr-x  2 root root  4096 2007-07-19 10:57 res
drwxr-xr-x  2 root root  4096 2007-07-19 10:57 security
drwxr-xr-x  2 root root  4096 2007-07-19 10:57 state
drwxr-xr-x  5 root root  4096 2007-07-19 10:57 taglib
drwxr-xr-x  5 root root  4096 2007-07-19 10:57 util


2. Decompiling


Once you find the class / classes that you need to change, you will need to decompile them.

I used a couple, and all worked pretty well.  They are windows tools, so I ended up decompiling in Windows, and building in Linux.  There are probably decompilers for Linux too, but I'll describe how I did it in Windows.


The two that I used were Cavaj Java Decompiler, and DJ Java Decompiler.  Both worked fine - in fact I think both use JAD as the decompiler behind the scenes (explaining why both sources ended up being the same).  DJ Java Decompiler is now shareware, not freeware, but I dug up an old version 3.7 that was freeware, and that worked a treat.


Some files, when decompiled, are not correct.  I have noticed some that complain there are missing blocks. Below is an example of one such file I found.


            while((bytesRead = != -1)
                outStream.write(buffer, 0, bytesRead);
        catch(SocketException e) { }
        break MISSING_BLOCK_LABEL_173;
        SocketException e;
        break MISSING_BLOCK_LABEL_173;
        SocketException e;
            if(inputStream != null)
        // Misplaced declaration of an exception variable
        catch(SocketException e) { }
        if(outStream != null)
          goto _L1
        JVM INSTR ret 11;


I would not play around with these files.  If you needed to change these files, I'd abort this approach and try something else.  You only want to be playing with JAVA files that make sense.


3. Recompiling


The problem now is to try to rebuild the decompiled java file.  Under Linux, I decided to create an Ant project, with minimal files in it.  I ended up getting it to work with the following directory structure.



  build.xml [see below]

  classes/ [ this is where the extracted jar files go ]











     [ this is the file that I want to edit.  The contents of this was from using a decompiler ]

  lib/  [this is where all the associated .jar files go. The package depends on these files. ]


Then I cobbled together a very basic build.xml file for myself, so that I could use Ant to build the java file.  The important think was that I needed all the class files in the class path, because in order to build the changed java file, you need to do so against the original class files.


An example build.xml file I created (and one that you can start off with) is:


  1 <?xml version="1.0" encoding="UTF-8"?>
  2 <project basedir="." default="jar">
  3     <!--Auto generated ant build file-->
  4     <property environment="env"/>
  5     <property name="project.base.dir" value="."/>
  6     <property name="maven.class.path" value=""/>
  7     <property name="name" value="blah"/>
  8     <property name="" value=""/>
  9     <property name="src" value="${project.base.dir}/src"/>
 10     <property name="test" value="${project.base.dir}/test"/>
 11     <property name="reference" value="${project.base.dir}/lib"/>
 12     <property name="build" value="${project.base.dir}/build"/>
 13     <property name="classes" value="${build}/classes"/>
 14     <property name="lib" value="${build}/lib"/>
 15     <path id="reference.class.path">
 16         <pathelement path="${java.class.path}" />
 17         <fileset dir="${reference}">
 18             <include name="*.jar" />
 19         </fileset>
 20     </path>
 21     <target name="init">
 22         <mkdir dir="${build}"/>
 23         <mkdir dir="${classes}"/>
 24         <mkdir dir="${lib}"/>
 25     </target>
 26     <target depends="init" name="pre.compile.test">
 27     </target>
 28     <target depends="pre.compile.test" name="compile.src">
 29         <javac debug="on" memoryMaximumSize="256m" memoryInitialSize="256m" fork="true" destdir="${classes}" srcdir="${src}">
 30             <classpath refid="reference.class.path" />
 31         </javac>
 32     </target>
 33     <target depends="compile.src" name="compile.test">
 34         <javac debug="on" memoryMaximumSize="256m" memoryInitialSize="256m" fork="true" destdir="${classes}">
 35             <src path="${test}"/>
 36             <classpath refid="reference.class.path" />
 37         </javac>
 38     </target>
 39     <target depends="compile.src" name="jar">
 40         <jar destfile="${lib}/${name}.jar">
 41             <fileset excludes="**/Test.class" dir="${classes}"/>
 42         </jar>
 43     </target>
 44     <target name="clean">
 45         <delete dir="${build}"/>
 46     </target>
 47 </project>


No, I don't use maven here, so you can probably remove or just ignore it (I left it here because I intend on migrating to maven at some stage).

After you edit your java files in the src directory, compile it using Ant.  You should have Ant and Java in your path already.


$ ant
Buildfile: build.xml

    [mkdir] Created dir: /home/aliu/sas.portal/build
    [mkdir] Created dir: /home/aliu/sas.portal/build/classes
    [mkdir] Created dir: /home/aliu/sas.portal/build/lib


    [javac] Compiling 1 source file to /home/aliu/sas.portal/build/classes

      [jar] Building jar: /home/aliu/sas.portal/build/lib/blah.jar

Total time: 1 second

$ ls -al build
total 16
drwxr-xr-x 4 root root 4096 2009-03-24 18:32 .
drwxrwxr-x 9 aliu aliu 4096 2009-03-24 18:32 ..
drwxr-xr-x 3 root root 4096 2009-03-24 18:32 classes
drwxr-xr-x 2 root root 4096 2009-03-24 18:32 lib
$ ls -al build/lib
total 12
drwxr-xr-x 2 root root 4096 2009-03-24 18:32 .
drwxr-xr-x 4 root root 4096 2009-03-24 18:32 ..
-rw-r--r-- 1 root root 3451 2009-03-24 18:32 blah.jar
$ ls -al build/classes/com/sas/portal/taglib/ui/PortalOptionsTag.class
-rw-r--r-- 1 root root 5704 2009-03-24 18:32 build/classes/com/sas/portal/taglib/ui/PortalOptionsTag.class


Here, we can see that there is a 'blah.jar' file, and the result CLASS file created.  We don't need the JAR file (hence the name of it) - what we are really after is the CLASS file.


4. Rebuilding the JAR file

Now that we have the CLASS files of the altered bits of code, we need to reinsert them back into the original JAR file.  We can do this using the 'jar' command.  Make sure you have backups of the original JAR file, as this will change the target JAR file!  Note that you will need to this from the correct location - from the same directory where the build.xml file is located.  You can specify the location of the JAR file relative from where you are, but the second argument (the CLASS file you are replacing) ** MUST ** be the same path as that within the original JAR file.


$ pwd


$ jar uvf ../sas.portal.jar com/sas/portal/taglib/ui/PortalOptionsTag.class
adding: com/sas/portal/taglib/ui/PortalOptionsTag.class(in = 5704) (out= 2422)(deflated 57%)

Now you have a new updated JAR file with your new CLASS file modification!

Note, this does not address updating the META-INF/MANIFEST.MF file.  To do this is more complicated, and has not been discussed in here.






Web News

Predictions 2020: RegTech funding will explode as VC investments in other markets cool
Tighter investor scrutiny will moderate venture capital and private equity investments. Meanwhile, regulatory technology funding will soar. Read our predictions.
--- 22 Nov 2019 05:14 AM

Ransomware: A free tool can decrypt this malware variant that puts a ransom note on you desktop wallpaper
The Hakbit ransomware is new but has some unusual features.
--- 22 Nov 2019 05:03 AM

Google will pay bug hunters up to $1.5m if they can hack its Titan M chip
Google increases bug bounty payouts because hacking Android is harder than it sounds.
--- 22 Nov 2019 04:00 AM

Xerox threatens to take its HP buyout offer to shareholders
Xerox is urging HP to reconsider its buyout offer or else it would take its case directly to HP's shareholders.
--- 22 Nov 2019 02:30 AM

Stephen Wolfram on the future of programming and why we live in a computational universe
The brains behind Mathematica, Wolfram|Alpha, and the Wolfram Language talks about how programming languages need to develop.
--- 22 Nov 2019 02:27 AM

Company Blog

Search Behaviour

Posted Tuesday, 19 October 2010 at 05:58 by Andrew Liu

As an SEO provider, you have one main goal. Get your clients website to show up in search results fo...


sm bus drivers missing in Device Manager

Posted Sunday, 18 April 2010
Updated Sunday, 24 February 2013 at 06:39 by Andrew Liu

When installing a new Windows XPinstallation, I seemingly always miss some drivers. One that trouble...


Multiple Domains for SEO performance?

Posted Friday, 05 March 2010 at 23:13 by Andrew Liu

Online businesses and websites that cover a broad range of topics or one large topic are sometimes b...


Tag Clouds - SEO or not?

Posted Thursday, 04 March 2010 at 04:34 by Andrew Liu

A tag cloud or word cloud is a visual depiction of tags or words related to a site, typically used t...


Mozilla Thunderbird and Gmail IMAP Attachments Bug

Posted Wednesday, 03 March 2010 at 20:15 by Andrew Liu

I've been using Gmail since its early inception, and Iwas one of the first to utilise Gmail's IMAPfe...


Read more blogs...