o  Javel version 0.3.2 - A Java disassembler


Content

Index

Software

Resources
      UML card
      VIM card
      CVS card
      Papers
      Icons
Bibliography

Resume

0xBABAF000L
Lune Melies Plantkelt.net

Introduction

Javel is a java class file disassembler. It is a filter that, given a compiled java class file, outputs a disassembled version in a java-like form with all the interface, fields, methods, and the java assembler code for each method. It can also output dependencies of the class file, suitable for inclusion in a standard makefile (like gcc -M or makedeps).

Download

You can freely download the source code of the latest version of Javel: javel0.3.2 .tar.gz . Makefile is not built from automake/autoconf, but since the compilation process is quite straightforward it should not be the cause of much trouble. You can then install javel by typing 'make' then (being root) 'make install'.

Internals

Javel is a kind of a specialized java class loader that loads from a stream a class file and builds from that a hierarchy of C++ objects that represents the corresponding java class. The root of the hierarchy is a class_info object, containing a vector of cp_info (constant pool descriptors), each of them being a specialized subclass of cp_info. The class descriptor contains also a vector of fields descriptors (field_info), a vector of methods descriptors (method_info), a list of implemented interfaces, a super class name, the name of the class itself and some further attributes (source line informations that maps pc to line number in the source code, source file info that give the source file name and location).

Each field_info contains its access flags, its type (a type_info object), and its name. Each method_info contains its access flags, its return type, parameters list, name and code (a code_info object). The code_info contains an array of bytes representing the source code of the method, a list of exception handler, and the stack and local variable pool size. Each exception handler maps a pc range [start_pc, end_pc) to an exception handler (handler_pc) and an exception type (a subclass of Throwable).

Future uses

The current use of Javel is for the moment to load a class, build the corresponding class_info and then, output the class_info to cout to obtain the dump of the disassembled version of the loaded class. But since Javel has been designed to be extensible, it would be possible to build some others application from this class loader base, like a small experimental jvm, a java debugger, a java runtime information extractor...

To do

  1. Remove the constant pool vector at the end of the loading process, since it should be unused after the construction of the class hierarchy.
  2. Analyze stack usage by tools.
  3. Dump the class file in XML format according to the JCX schema.

Output format

The format of the interface produced follows java standards and should be understood without any problems. The format for the code section of methods is the following: For more informations on the opcode list and their exact meaning, we strongly recommand reading the Sun's JVM specifications, second edition, that can be obtained online on the Sun's website.

Usage

Javel can be used with one or multiple class file name as arguments. Many options can be specified along. To have the complete list of arguments, just type javel -help or even javel alone. For example, if you want to dump the information of Test.class, you just have to type javel Test.class. You can of course redirect the output to a file for further uses. If you want the code dumped, specify '-v'.

(De)compilation of iteration statements

Here is a short description of the bytecode output produced by a classic java compiler with all branch statements (while, do, for, if):

schema on pcode branching

From left to right:
while loop:
while (Cond) {
	Oper;
}
do loop:
do {
	Oper;
} while(cond);
for loop:
for(Init; Cond; Oper1) {
	Oper2;
}
if/then/else conditional:
if (Cond) {
	Oper1;
} else {
	Oper2;
}

You can easily notice that, since there is no way to find the frontier between two blocks of bytecode when there is no jumps (either starting or ending) at the frontier, the compiled for cannot be distincted from a while, where Oper = Oper1 + Oper2, and Init the code before the beginning of the while. For real decompilation, we should then use some heuristics to discriminate the common for from the less common while form.

JCX - Java Class file in XML

Here you will find the XML schema definition for a representation of Java class file in XML format.
<?xml version='1.0' encoding='UTF-8'?>

<schema
 targetNamespace='http://tnerual.eriogerg.free.fr/jcx-1.0'
 xmlns:jcx='http://tnerual.eriogerg.free.fr/jcx-1.0'
 xmlns='http://www.w3.org/2001/XMLSchema'
 elementFormDefault='qualified'>

  <!-- Documentation -->
  <annotation>
    <documentation>
      Schema for JCX - Java Class in XML.
    </documentation>
  </annotation>

  <!-- Base element definition -->
  <element name='jcx' type='jcx:jcxType'/>

  <!-- Main element definition -->
  <complexType name='jcxType'>
    <sequence>
      <element name='classes' type='jcx:classListType'/>
    </sequence>
    <attribute name='version' type='jcx:versionType' use='required'/>
  </complexType>

  <!-- Class list definition -->
  <complexType name='classListType'>
    <sequence>
      <element name='class' type='jcx:classType'
       minOccurs='0' maxOccurs='unbounded'/>
    </sequence>
  </complexType>

  <!-- Main class type definition -->
  <complexType name='classType'>
    <sequence>
      <element name='visibility' type='jcx:visibilityType'
       minOccurs='0' maxOccurs='1'/>
      <element name='final' type='jcx:boolType'
       minOccurs='0' maxOccurs='1'/>
      <element name='static' type='jcx:boolType'
       minOccurs='0' maxOccurs='1'/>
      <element name='extends' type='jcx:classRefType'
       minOccurs='0' maxOccurs='1'/>
      <element name='implements' type='jcx:classRefType'
       minOccurs='0' maxOccurs='unbounded'/>
      <element name='field' type='jcx:fieldType'
       minOccurs='0' maxOccurs='unbounded'/>
      <element name='method' type='jcx:methodType'
       minOccurs='0' maxOccurs='unbounded'/>
    </sequence>
    <attribute name='name' type='jcx:classNameType' use='required'/>
  </complexType>

  <!-- Class name definition -->
  <simpleType name='classNameType'>
    <restriction base='token'>
    </restriction>
  </simpleType>

  <!-- Identifier name definition -->
  <simpleType name='idNameType'>
    <restriction base='token'>
    </restriction>
  </simpleType>

  <!-- Type name definition -->
  <simpleType name='typeNameType'>
    <restriction base='token'>
    </restriction>
  </simpleType>

  <!-- Value definition -->
  <simpleType name='valueType'>
    <restriction base='token'>
    </restriction>
  </simpleType>

  <!-- Visibility type definition -->
  <complexType name='visibilityType'>
    <attribute name='value' type='jcx:visibilityValueType' default='package'/>
  </complexType>

  <!-- Class visibility values definition -->
  <simpleType name='visibilityValueType'>
    <restriction base='token'>
      <enumeration value='public'/>
      <enumeration value='package'/>
      <enumeration value='protected'/>
      <enumeration value='private'/>
    </restriction>
  </simpleType>

  <!-- Empty type for tags definition -->
  <complexType name='boolType'>
    <attribute name='value' type='boolean' default='true'/>
  </complexType>

  <!-- Class reference definition -->
  <complexType name='classRefType'>
    <attribute name='class' type='jcx:classNameType' use='required'/>
  </complexType>

  <!-- Field type definition -->
  <complexType name='fieldType'>
    <sequence>
      <element name='visibility' type='jcx:visibilityType'
       minOccurs='0' maxOccurs='1'/>
      <element name='final' type='jcx:boolType'
       minOccurs='0' maxOccurs='1'/>
      <element name='static' type='jcx:boolType'
       minOccurs='0' maxOccurs='1'/>
      <element name='value' type='jcx:valueType'
       minOccurs='0' maxOccurs='1'/>
    </sequence>
    <attribute name='name' type='jcx:idNameType' use='required'/>
    <attribute name='type' type='jcx:typeNameType' use='required'/>
  </complexType>

  <!-- Method type definition -->
  <complexType name='methodType'>
    <sequence>
      <element name='visibility' type='jcx:visibilityType'
       minOccurs='0' maxOccurs='1'/>
      <element name='abstract' type='jcx:boolType'
       minOccurs='0' maxOccurs='1'/>
      <element name='static' type='jcx:boolType'
       minOccurs='0' maxOccurs='1'/>
      <element name='parameters' type='jcx:parameterListType'/>
    </sequence>
    <attribute name='name' type='jcx:idNameType' use='required'/>
    <attribute name='type' type='jcx:typeNameType' use='required'/>
  </complexType>

  <!-- Parameter list definition -->
  <complexType name='parameterListType'>
    <sequence>
      <element name='param' type='jcx:parameterType'
       minOccurs='0' maxOccurs='unbounded'/>
    </sequence>
  </complexType>

  <!-- Parameter definition -->
  <complexType name='parameterType'>
    <attribute name='name' type='jcx:idNameType' use='required'/>
    <attribute name='type' type='jcx:typeNameType' use='required'/>
  </complexType>

  <!-- JCX version definition -->
  <simpleType name='versionType'>
    <restriction base='token'>
      <enumeration value='1.0'/>
    </restriction>
  </simpleType>

</schema>



$Id: javel.wml,v 1.2 2002/05/29 15:22:47 laurent Exp $
Valid HTML 4.01!Copyright © 2001-2007 Laurent Grégoire <laurent.gregoire@gmail.com> - Generated from 'javel.wml' on 2005-12-02 19:24:19 with the WML scripting language on a Linux 2.6.28-13-generic box - Source file edited with vim.