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.

 

        try
        {
            while((bytesRead = inputStream.read(buffer)) != -1)
                outStream.write(buffer, 0, bytesRead);
            outStream.flush();
        }
        catch(SocketException e) { }
        break MISSING_BLOCK_LABEL_173;
        SocketException e;
        e;
        break MISSING_BLOCK_LABEL_173;
        local;
        SocketException e;
        try
        {
            if(inputStream != null)
                inputStream.close();
        }
        // Misplaced declaration of an exception variable
        catch(SocketException e) { }
        if(outStream != null)
            outStream.close();
          goto _L1
        e;
_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.

 

sas.portal/

  build.xml [see below]

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

    com/

      sas/

        portal/

          ...

  src/

    com/

      sas/

        portal/

          ui/

            taglib/

              PortalOptions.java [ 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="user.email" value="andrew.liu@webtop.com.au"/>
  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

init:
    [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

pre.compile.test:

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

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

BUILD SUCCESSFUL
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

/home/aliu/sas.portal

$ 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

Symantec distrust to begin in Chrome from April 2018
Google's browser will start the process of removing trust from old Symantec TLS certificates in Chrome 66.
--- 28 Jul 2017 01:42 PM

Ok Google: Telstra adds Google Home to smart home offering
The telco giant has welcomed Google into its Smart Home play.
--- 28 Jul 2017 01:08 PM

Huawei reports 15 percent revenue surge for H1 2017
The networking giant generated 283.1 billion yuan in revenue during the first six months of 2017.
--- 28 Jul 2017 12:47 PM

LG posts healthy Q2 profit despite mobile setback
Marketing costs for the new G6 tinted an otherwise strong quarter for LG Electronics.
--- 28 Jul 2017 11:53 AM

Singapore should not criminalise good intent to encourage data sharing in cybersecurity
People who fear prosecution may be less willing to share threat information, which is vital in fending off attacks, and Singapore government should clearly define its proposed mandate for companies to report data breaches within 72 hours.
--- 28 Jul 2017 11:23 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...

Read more...



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...

Read more...



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...

Read more...



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...

Read more...



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...



Read more blogs...