Compare commits

..

14 Commits

Author SHA1 Message Date
jochen b863984781 fixed a bug, when MONITOREXIT is outside of the try block for synchronized 25 years ago
jochen d49e59a3ef added bin subdirectory 25 years ago
jochen f6f2987fad added bin and java sub directories 25 years ago
jochen 62e7cb80d6 added makefile 25 years ago
jochen ed0f34efba added makefile 25 years ago
jochen 8377de22ad handle --classpath option 25 years ago
jochen ddad164a2e fixed some bugs, handle delay loading of ALL_ATTRIBUTE 25 years ago
jochen 20d93c44fe lots of bugs fixed 25 years ago
jochen 4ae713d9a6 handle --classpath option, to unify the names 25 years ago
jochen 2d2c71bdb9 merged autoconf/automake thingy in stable tree 25 years ago
(no author) e3d7a55d64 This commit was manufactured by cvs2svn to create branch 'stable'. 25 years ago
jochen 999834f14d simplify all flow blocks 25 years ago
jochen fc1da2077a fixed some bugs 25 years ago
(no author) 70a8181fce This commit was manufactured by cvs2svn to create branch 'stable'. 25 years ago
  1. 14
      CVSROOT/checkoutlist
  2. 15
      CVSROOT/commitinfo
  3. 11
      CVSROOT/config
  4. 1
      CVSROOT/cvsignore
  5. 24
      CVSROOT/cvswrappers
  6. 21
      CVSROOT/editinfo
  7. 27
      CVSROOT/loginfo
  8. 1
      CVSROOT/modules
  9. 12
      CVSROOT/notify
  10. 13
      CVSROOT/rcsinfo
  11. 206
      CVSROOT/syncmail
  12. 20
      CVSROOT/taginfo
  13. 21
      CVSROOT/verifymsg
  14. 7
      jode/.classpath
  15. 17
      jode/.project
  16. 353
      jode/.settings/org.eclipse.jdt.core.prefs
  17. 4
      jode/.settings/org.eclipse.jdt.ui.prefs
  18. 3
      jode/.settings/org.eclipse.ltk.core.refactoring.prefs
  19. 2
      jode/AUTHORS
  20. 504
      jode/COPYING.LESSER
  21. 504
      jode/COPYING.LGPL
  22. 563
      jode/ChangeLog
  23. 56
      jode/INSTALL
  24. 3
      jode/MANIFEST.MF
  25. 5
      jode/Makefile.am
  26. 36
      jode/NEWS
  27. 194
      jode/README
  28. 5
      jode/THANKS
  29. 56
      jode/TODO
  30. 44
      jode/acinclude.m4
  31. 29
      jode/addHeader.pl
  32. 3
      jode/bin/Makefile.am
  33. 19
      jode/bin/jode.bat.in
  34. 4
      jode/bin/jode.in
  35. 380
      jode/build.xml
  36. 28
      jode/config.props
  37. 139
      jode/configure.in
  38. 58
      jode/create.sh
  39. 1
      jode/doc/.cvsignore
  40. 5
      jode/doc/Makefile.am
  41. 25
      jode/doc/applet.htp
  42. 69
      jode/doc/bluesky.htp
  43. 711
      jode/doc/dasm_to_java.perl
  44. 39
      jode/doc/download.htp
  45. 90
      jode/doc/faq.htp
  46. 106
      jode/doc/favicon.xpm
  47. 11
      jode/doc/feedback.htp
  48. 13
      jode/doc/footer.inc
  49. BIN
      jode/doc/gimp/arrow.gif
  50. BIN
      jode/doc/gimp/bytecode.gif
  51. 9
      jode/doc/gimp/bytecode.txt
  52. BIN
      jode/doc/gimp/flow.gif
  53. BIN
      jode/doc/gimp/jode-logo.xcf
  54. BIN
      jode/doc/gimp/statement.gif
  55. 9
      jode/doc/gimp/statement.txt
  56. 42
      jode/doc/gimp/vects.fig
  57. 63
      jode/doc/header.inc
  58. 20
      jode/doc/history.htp
  59. 52
      jode/doc/htp.def
  60. 74
      jode/doc/index.htp
  61. 39
      jode/doc/jode-applet.html
  62. BIN
      jode/doc/jode-logo.png
  63. 15
      jode/doc/jode-obfuscator.html
  64. 97
      jode/doc/jode-unix.html
  65. 49
      jode/doc/jode-useapplet.html
  66. 62
      jode/doc/jode-win.html
  67. 125
      jode/doc/jode.html
  68. 67
      jode/doc/jode.htt
  69. 21
      jode/doc/license.htp
  70. 75
      jode/doc/links.htp
  71. 47
      jode/doc/menu.inc
  72. 84
      jode/doc/myproject.jos
  73. BIN
      jode/doc/poweredbyhtp.png
  74. 62
      jode/doc/technical.texi
  75. 250
      jode/doc/usage.htp
  76. BIN
      jode/doc/w3c_ab.png
  77. 99
      jode/jcpp
  78. 4
      jode/jode/.cvsignore
  79. 13
      jode/jode/AssertError.java
  80. 284
      jode/jode/Decompiler.java
  81. 24
      jode/jode/GlobalOptions.java.in
  82. 46
      jode/jode/JodeApplet.java
  83. 85
      jode/jode/JodeWindow.java
  84. 54
      jode/jode/Makefile.am
  85. 2
      jode/jode/bytecode/.cvsignore
  86. 201
      jode/jode/bytecode/BinaryInfo.java
  87. 1127
      jode/jode/bytecode/BytecodeInfo.java
  88. 33
      jode/jode/bytecode/ClassFormatException.java
  89. 780
      jode/jode/bytecode/ClassInfo.java
  90. 189
      jode/jode/bytecode/ConstantPool.java
  91. 195
      jode/jode/bytecode/FieldInfo.java
  92. 257
      jode/jode/bytecode/GrowableConstantPool.java
  93. 18
      jode/jode/bytecode/Handler.java
  94. 37
      jode/jode/bytecode/InnerClassInfo.java
  95. 492
      jode/jode/bytecode/Instruction.java
  96. 29
      jode/jode/bytecode/LineNumber.java
  97. 30
      jode/jode/bytecode/LocalVariableInfo.java
  98. 46
      jode/jode/bytecode/Makefile.am
  99. 227
      jode/jode/bytecode/MethodInfo.java
  100. 22
      jode/jode/bytecode/Opcodes.java
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,14 +0,0 @@
# The "checkoutlist" file is used to support additional version controlled
# administrative files in $CVSROOT/CVSROOT, such as template files.
#
# The first entry on a line is a filename which will be checked out from
# the corresponding RCS file in the $CVSROOT/CVSROOT directory.
# The remainder of the line is an error message to use if the file cannot
# be checked out.
#
# File format:
#
# [<whitespace>]<filename><whitespace><error message><end-of-line>
#
# comment lines begin with '#'
syncmail

@ -1,15 +0,0 @@
# The "commitinfo" file is used to control pre-commit checks.
# The filter on the right is invoked with the repository and a list
# of files to check. A non-zero exit of the filter program will
# cause the commit to be aborted.
#
# The first entry on a line is a regular expression which is tested
# against the directory that the change is being committed to, relative
# to the $CVSROOT. For the first match that is found, then the remainder
# of the line is the name of the filter to run.
#
# If the repository name does not match any of the regular expressions in this
# file, the "DEFAULT" line is used, if it is specified.
#
# If the name "ALL" appears as a regular expression it is always used
# in addition to the first matching regex or "DEFAULT".

@ -1,11 +0,0 @@
# Set this to "no" if pserver shouldn't check system users/passwords
#SystemAuth=no
# Set `PreservePermissions' to `yes' to save file status information
# in the repository.
#PreservePermissions=no
# Set `TopLevelAdmin' to `yes' to create a CVS directory at the top
# level of the new working directory when using the `cvs checkout'
# command.
#TopLevelAdmin=no

@ -1,24 +0,0 @@
# This file affects handling of files based on their names.
#
# The -t/-f options allow one to treat directories of files
# as a single file, or to transform a file in other ways on
# its way in and out of CVS.
#
# The -m option specifies whether CVS attempts to merge files.
#
# The -k option specifies keyword expansion (e.g. -kb for binary).
#
# Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers)
#
# wildcard [option value][option value]...
#
# where option is one of
# -f from cvs filter value: path to filter
# -t to cvs filter value: path to filter
# -m update methodology value: MERGE or COPY
# -k expansion mode value: b, o, kkv, &c
#
# and value is a single-quote delimited value.
# For example:
*.gif -k 'b'
*.xcf -k 'b'

@ -1,21 +0,0 @@
# The "editinfo" file is used to allow verification of logging
# information. It works best when a template (as specified in the
# rcsinfo file) is provided for the logging procedure. Given a
# template with locations for, a bug-id number, a list of people who
# reviewed the code before it can be checked in, and an external
# process to catalog the differences that were code reviewed, the
# following test can be applied to the code:
#
# Making sure that the entered bug-id number is correct.
# Validating that the code that was reviewed is indeed the code being
# checked in (using the bug-id number or a seperate review
# number to identify this particular code set.).
#
# If any of the above test failed, then the commit would be aborted.
#
# Actions such as mailing a copy of the report to each reviewer are
# better handled by an entry in the loginfo file.
#
# One thing that should be noted is the the ALL keyword is not
# supported. There can be only one entry that matches a given
# repository.

@ -1,27 +0,0 @@
# The "loginfo" file controls where "cvs commit" log information
# is sent. The first entry on a line is a regular expression which must match
# the directory that the change is being made to, relative to the
# $CVSROOT. If a match is found, then the remainder of the line is a filter
# program that should expect log information on its standard input.
#
# If the repository name does not match any of the regular expressions in this
# file, the "DEFAULT" line is used, if it is specified.
#
# If the name ALL appears as a regular expression it is always used
# in addition to the first matching regex or DEFAULT.
#
# You may specify a format string as part of the
# filter. The string is composed of a `%' followed
# by a single format character, or followed by a set of format
# characters surrounded by `{' and `}' as separators. The format
# characters are:
#
# s = file name
# V = old version number (pre-checkin)
# v = new version number (post-checkin)
#
# For example:
#DEFAULT (echo ""; id; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog
# or
#DEFAULT (echo ""; id; echo %{sVv}; date; cat) >> $CVSROOT/CVSROOT/commitlog
DEFAULT $CVSROOT/CVSROOT/syncmail %{sVv} jode-commit@lists.sourceforge.net

@ -1 +0,0 @@
jode jode

@ -1,12 +0,0 @@
# The "notify" file controls where notifications from watches set by
# "cvs watch add" or "cvs edit" are sent. The first entry on a line is
# a regular expression which is tested against the directory that the
# change is being made to, relative to the $CVSROOT. If it matches,
# then the remainder of the line is a filter program that should contain
# one occurrence of %s for the user to notify, and information on its
# standard input.
#
# "ALL" or "DEFAULT" can be used in place of the regular expression.
#
# For example:
#ALL mail %s -s "CVS notification"

@ -1,13 +0,0 @@
# The "rcsinfo" file is used to control templates with which the editor
# is invoked on commit and import.
#
# The first entry on a line is a regular expression which is tested
# against the directory that the change is being made to, relative to the
# $CVSROOT. For the first match that is found, then the remainder of the
# line is the name of the file that contains the template.
#
# If the repository name does not match any of the regular expressions in this
# file, the "DEFAULT" line is used, if it is specified.
#
# If the name "ALL" appears as a regular expression it is always used
# in addition to the first matching regex or "DEFAULT".

@ -1,206 +0,0 @@
#! /usr/bin/python
# -*- Python -*-
"""Complicated notification for CVS checkins.
This script is used to provide email notifications of changes to the CVS
repository. These email changes will include context diffs of the changes.
Really big diffs will be trimmed.
This script is run from a CVS loginfo file (see $CVSROOT/CVSROOT/loginfo). To
set this up, create a loginfo entry that looks something like this:
mymodule /path/to/this/script %%s some-email-addr@your.domain
In this example, whenever a checkin that matches `mymodule' is made, this
script is invoked, which will generate the diff containing email, and send it
to some-email-addr@your.domain.
Note: This module used to also do repository synchronizations via
rsync-over-ssh, but since the repository has been moved to SourceForge,
this is no longer necessary. The syncing functionality has been ripped
out in the 3.0, which simplifies it considerably. Access the 2.x versions
to refer to this functionality. Because of this, the script is misnamed.
It no longer makes sense to run this script from the command line. Doing so
will only print out this usage information.
Usage:
%(PROGRAM)s [options] <%%S> email-addr [email-addr ...]
Where options is:
--cvsroot=<path>
Use <path> as the environment variable CVSROOT. Otherwise this
variable must exist in the environment.
--help
-h
Print this text.
<%%S>
CVS %%s loginfo expansion. When invoked by CVS, this will be a single
string containing the directory the checkin is being made in, relative
to $CVSROOT, followed by the list of files that are changing. If the
%%s in the loginfo file is %%{sVv}, context diffs for each of the
modified files are included in any email messages that are generated.
email-addrs
At least one email address.
"""
import os
import sys
import string
import time
import getopt
# Notification command
MAILCMD = '/bin/mail -s "%(SUBJECT)s" %(PEOPLE)s 2>&1 > /dev/null'
# Diff trimming stuff
DIFF_HEAD_LINES = 20
DIFF_TAIL_LINES = 20
DIFF_TRUNCATE_IF_LARGER = 1000
PROGRAM = sys.argv[0]
def usage(code, msg=''):
print __doc__ % globals()
if msg:
print msg
sys.exit(code)
def calculate_diff(filespec):
try:
file, oldrev, newrev = string.split(filespec, ',')
except ValueError:
# No diff to report
return '***** Bogus filespec: %s' % filespec
if oldrev == 'NONE':
try:
if os.path.exists(file):
fp = open(file)
else:
update_cmd = 'cvs -fn update -r %s -p %s' % (newrev, file)
fp = os.popen(update_cmd)
lines = fp.readlines()
fp.close()
lines.insert(0, '--- NEW FILE ---\n')
except IOError, e:
lines = ['***** Error reading new file: ',
str(e), '\n***** file: ', file, ' cwd: ', os.getcwd()]
elif newrev == 'NONE':
lines = ['--- %s DELETED ---\n' % file]
else:
# This /has/ to happen in the background, otherwise we'll run into CVS
# lock contention. What a crock.
diffcmd = '/usr/bin/cvs -f diff -kk -C 2 -r %s -r %s %s' % (
oldrev, newrev, file)
fp = os.popen(diffcmd)
lines = fp.readlines()
sts = fp.close()
# ignore the error code, it always seems to be 1 :(
## if sts:
## return 'Error code %d occurred during diff\n' % (sts >> 8)
if len(lines) > DIFF_TRUNCATE_IF_LARGER:
removedlines = len(lines) - DIFF_HEAD_LINES - DIFF_TAIL_LINES
del lines[DIFF_HEAD_LINES:-DIFF_TAIL_LINES]
lines.insert(DIFF_HEAD_LINES,
'[...%d lines suppressed...]\n' % removedlines)
return string.join(lines, '')
def calculate_url(dir, filespec):
try:
file, oldrev, newrev = string.split(filespec, ',')
except ValueError:
# No diff to report
return '***** Bogus filespec: %s' % filespec
if oldrev == 'NONE':
lines = [ 'http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/jode/%s/%s?rev=%s' % (dir, file, newrev) ]
elif newrev == 'NONE':
lines = [ 'DELETED: http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/jode/%s/%s?rev=%s' % (dir, file, oldrev) ]
else:
lines = [ 'http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/jode/%s/%s.diff?r1=%s&r2=%s&diff_format=u' % (dir, file, oldrev, newrev) ]
return string.join(lines, '')
def blast_mail(mailcmd, dir, filestodiff):
## cannot wait for child process or that will cause parent to retain cvs
## lock for too long. Urg!
#if not os.fork():
# in the child
# give up the lock you cvs thang!
time.sleep(2)
fp = os.popen(mailcmd, 'w')
fp.write(sys.stdin.read())
fp.write('\n')
# append the cvsweb urls if available
fp.write('CVSWeb URLs:\n');
for file in filestodiff:
# fp.write(calculate_diff(file))
fp.write(calculate_url(dir, file))
fp.write('\n')
fp.close()
## doesn't matter what code we return, it isn't waited on
# os._exit(0)
# scan args for options
def main():
try:
opts, args = getopt.getopt(sys.argv[1:], 'h', ['cvsroot=', 'help'])
except getopt.error, msg:
usage(1, msg)
# parse the options
for opt, arg in opts:
if opt in ('-h', '--help'):
usage(0)
elif opt == '--cvsroot':
os.environ['CVSROOT'] = arg
# What follows is the specification containing the files that were
# modified. The argument actually must be split, with the first component
# containing the directory the checkin is being made in, relative to
# $CVSROOT, followed by the list of files that are changing.
if not args:
usage(1, 'No CVS module specified')
specs = string.split(args[0])
changedfiles = [ specs[0] ];
for filespec in specs[1:]:
try:
file, oldrev, newrev = string.split(filespec, ',')
changedfiles.append(file)
except ValueError:
changedfiles.append(filespec)
SUBJECT = string.join(changedfiles, ' ')
del args[0]
# The remaining args should be the email addresses
if not args:
usage(1, 'No recipients specified')
# Now do the mail command
PEOPLE = string.join(args)
mailcmd = MAILCMD % vars()
if specs == ['-', 'Imported', 'sources']:
return
if specs[-3:] == ['-', 'New', 'directory']:
del specs[-3:]
blast_mail(mailcmd, specs[0], specs[1:])
if __name__ == '__main__':
main()
sys.exit(0)

@ -1,20 +0,0 @@
# The "taginfo" file is used to control pre-tag checks.
# The filter on the right is invoked with the following arguments:
#
# $1 -- tagname
# $2 -- operation "add" for tag, "mov" for tag -F, and "del" for tag -d
# $3 -- repository
# $4-> file revision [file revision ...]
#
# A non-zero exit of the filter program will cause the tag to be aborted.
#
# The first entry on a line is a regular expression which is tested
# against the directory that the change is being committed to, relative
# to the $CVSROOT. For the first match that is found, then the remainder
# of the line is the name of the filter to run.
#
# If the repository name does not match any of the regular expressions in this
# file, the "DEFAULT" line is used, if it is specified.
#
# If the name "ALL" appears as a regular expression it is always used
# in addition to the first matching regex or "DEFAULT".

@ -1,21 +0,0 @@
# The "verifymsg" file is used to allow verification of logging
# information. It works best when a template (as specified in the
# rcsinfo file) is provided for the logging procedure. Given a
# template with locations for, a bug-id number, a list of people who
# reviewed the code before it can be checked in, and an external
# process to catalog the differences that were code reviewed, the
# following test can be applied to the code:
#
# Making sure that the entered bug-id number is correct.
# Validating that the code that was reviewed is indeed the code being
# checked in (using the bug-id number or a seperate review
# number to identify this particular code set.).
#
# If any of the above test failed, then the commit would be aborted.
#
# Actions such as mailing a copy of the report to each reviewer are
# better handled by an entry in the loginfo file.
#
# One thing that should be noted is the the ALL keyword is not
# supported. There can be only one entry that matches a given
# repository.

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry excluding="net/sf/jode/obfuscator/modules/LocalOptimizer.java|net/sf/jode/obfuscator/modules/LocalizeFieldTransformer.java|net/sf/jode/obfuscator/modules/RemovePopAnalyzer.java" kind="src" output="build" path="src"/>
<classpathentry kind="lib" path="lib/java-getopt-1.0.8.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="build"/>
</classpath>

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>jode</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

@ -1,353 +0,0 @@
#Thu Mar 01 23:39:18 CET 2012
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.4
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
org.eclipse.jdt.core.compiler.problem.deadCode=warning
org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
org.eclipse.jdt.core.compiler.problem.nullReference=warning
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
org.eclipse.jdt.core.compiler.problem.unusedImport=warning
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.source=1.3
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
org.eclipse.jdt.core.formatter.blank_lines_before_field=0
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
org.eclipse.jdt.core.formatter.blank_lines_before_method=1
org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
org.eclipse.jdt.core.formatter.blank_lines_before_package=0
org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
org.eclipse.jdt.core.formatter.comment.format_block_comments=true
org.eclipse.jdt.core.formatter.comment.format_header=false
org.eclipse.jdt.core.formatter.comment.format_html=true
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
org.eclipse.jdt.core.formatter.comment.format_line_comments=true
org.eclipse.jdt.core.formatter.comment.format_source_code=true
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
org.eclipse.jdt.core.formatter.comment.line_length=80
org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
org.eclipse.jdt.core.formatter.compact_else_if=true
org.eclipse.jdt.core.formatter.continuation_indentation=2
org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_empty_lines=false
org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
org.eclipse.jdt.core.formatter.indentation.size=4
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.join_lines_in_comments=true
org.eclipse.jdt.core.formatter.join_wrapped_lines=true
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.jdt.core.formatter.lineSplit=80
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.jdt.core.formatter.tabulation.char=mixed
org.eclipse.jdt.core.formatter.tabulation.size=8
org.eclipse.jdt.core.formatter.use_on_off_tags=false
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true

@ -1,4 +0,0 @@
#Thu Mar 01 22:21:28 CET 2012
eclipse.preferences.version=1
formatter_profile=org.eclipse.jdt.ui.default.sun_profile
formatter_settings_version=12

@ -1,3 +0,0 @@
#Thu Mar 01 22:15:48 CET 2012
eclipse.preferences.version=1
org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false

@ -1 +1 @@
Jochen Hoenicke <Jochen.Hoenicke@Informatik.Uni-Oldenburg.DE>
Jochen Hoenicke <Jochen.Hoenicke@Informatik.Uni-Oldenburg.DE>

@ -1,504 +0,0 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

@ -1,504 +0,0 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

@ -1,563 +0,0 @@
2005-10-14 Jochen Hoenicke <jochen@gnu.org>
* src/net/sf/jode/flow/TransformConstructor.java:
(lookForConstructorCall) Check for isStatic before setting
outer $this reference
(reported by Andreas Salathé, bug #1306688)
2005-09-13 Jochen Hoenicke <jochen@gnu.org>
Check for NullPointer in SyntheticAnalyzer. Based on
patch suggessted by Peter Klauser (klp at users.sf.net).
* src/net/sf/jode/jvm/SyntheticAnalyzer.java:
(checkStaticAccess): Check refField for null pointer.
(checkAccess): Likewise.
2004-08-06 Jochen Hoenicke <hoenicke@marge.Informatik.Uni-Oldenburg.DE>
* src/net/sf/jode/bytecode/BinaryInfo.java (ACC_*): added
constants describing modifier attributes.
* src/net/sf/jode/bytecode/BasicBlockReader.java
(convertHandlers): remove empty handlers.
(readCode): merge adjacent try-blocks (splitted by javac-1.4
return rule).
* src/net/sf/jode/bytecode/FieldInfo.java (syntheticFlag):
removed, use modifier and ACC_SYNTHETIC (new in java 5) instead.
Changed all usages. When writing it currently writes out both
old and new synthetic format.
(getSignature): New method to return full generic signature.
* src/net/sf/jode/bytecode/MethodInfo.java
(syntheticFlag, getSignature): likewise.
* src/net/sf/jode/bytecode/ClassInfo.java (getSignature):
New method to return full generic signature.
* src/net/sf/jode/decompiler/MethodAnalyzer.java (skipWriting):
Skip java 5 bridge methods.
* src/net/sf/jode/expr/InvokeOperator.java (getClassAnalyzer):
Check for null callee.
* src/net/sf/jode/expr/FlowBlock.java (analyze): New order for
T1,T2 analysis: Do not do T1 analysis when the block has more
than one real successor and the next block can be easily merged.
See comment for more information.
2004-08-05 Jochen Hoenicke <hoenicke@marge.Informatik.Uni-Oldenburg.DE>
* build.xml: replace execon with apply.
* src/net/sf/jode/bytecode/ClassInfo.java (readAttributes):
read in signature attribute (not yet published, though).
* src/net/sf/jode/bytecode/MethodInfo.java (readAttributes):
likewise.
* src/net/sf/jode/bytecode/FieldInfo.java (readAttributes):
likewise.
* src/net/sf/jode/bytecode/ClassInfo.java (mergeModifiers):
only check the traditional modifiers for equality.
* src/net/sf/jode/bytecode/ConstantPool.java (getConstant):
Support for CLASS constants (jdk1.5) added.
* src/net/sf/jode/bytecode/BasicBlockReader.java (readCode):
opc_ldc, opc_ldc_w: Support for CLASS constants added.
* src/net/sf/jode/decompiler/Opcodes.java (addOpcode):
likewise.
* src/net/sf/jode/expr/InvokeOperator.java
(simplifyStringBuffer, simplifyString):
Also handle StringBuilder (jdk1.5).
* src/net/sf/jode/type/Type.java (tStringBuilder): new field.
* src/net/sf/jode/swingui/Main.java (main): handle debug
options.
2004-01-31 Jochen Hoenicke <hoenicke@informatik.uni-oldenburg.de>
* src/net/sf/jode/jvm/SyntheticAnalyzer.java (checkGetClass):
Handle jdk1.4 class$ methods.
* src/net/sf/jode/jvm/RuntimeEnvironment.java: Fixed some javadocs.
* src/net/sf/jode/flow/CompleteSynchronized.java: likewise.
* src/net/sf/jode/flow/CreateExpression.java: likewise.
* src/net/sf/jode/flow/CreateIfThenElseOperator.java: likewise.
Added changes (except obfuscator changes) from jode-1.1 tree up to
2001-07-08
* src/net/sf/jode/bytecode/ClassInfo.java (deprecatedFlag): Added
flag for deprecated classes. Stuart Ballard noticed that this was
missing.
(readAttribute): Read deprecated attribute.
(prepareWriting): Prepare deprecated attribute.
(writeKnownAttributes): Write deprecated attribute.
(isDeprected): New function.
(setDeprecated): Likewise.
* src/net/sf/jode/bytecode/BasicBlockReader.java (readCode): Fix
the exception handlers that javac 1.4 produces: I simply shorten
the start/end interval, so that the catcher is not in the end
interval.
* src/net/sf/jode/flow/CreateAssignExpression.java
(createAssignOp): Bug fix: Check whether store is already a
op-assign and break out.
* src/net/sf/jode/expr/StoreInstruction.java (isOpAssign): New
function to check whether this is an op-assign.
* src/net/sf/jode/flow/CatchBlock.java (combineLocal): Added more
checks if LocalStoreOperator is of the right form.
* net/sf/jode/flow/TransformConstructors.java (Constructor): Ignore
OuterValues for static constructor.
* src/net/sf/jode/expr/CompareToIntOperator.java (dumpExpression):
Added a missing breakOp.
2004-01-22 Jochen Hoenicke <hoenicke@informatik.uni-oldenburg.de>
* net/sf/jode/jvm/CodeVerifier.java (modelEffect): Allow assigning
fields in an uninitialized class as some synthetic code does this.
2003-06-11 Mark Morschhäuser <mark.morschhaeuser@firemail.de>
* net/sf/jode/decompiler/Main.java: New MenuItem to save a decompiled file.
* net/sf/jode/decompiler/Main.java: Main-window will be centered on startup
* build.xml:
(release): Added MANIFEST.MF to target and enabled compressed jar-file
* MANIFEST.MF: Added this file to be able to create an executable jar-file
2002-06-11 Jochen Hoenicke <jochen@gnu.org>
* net/sf/jode/decompiler/Main.java: New option keep-alive. With
this option jode won't stop after an error but will continue with
the next class.
Patch suggested by Francis Devereux, francis at hc.eclipse.co.uk
2002-02-25 Jochen Hoenicke <jochen@gnu.org>
* jode/bytecode/ClassInfo.java.in (read): Don't check for a
maximum version anymore. Sun changes it with every release without
changing the bytecode format.
2002-02-15 Jochen Hoenicke <jochen@gnu.org>
* net/sf/jode/bytecode/BasicBlockReader.java: handle empty loops.
(IS_NULL): new constant to tag empty blocks.
(markReachableBlocks): check for empty loops.
(convertBlock): Handle empty blocks.
(convert): Handle IS_NULL.
* net/sf/jode/decompiler/MethodAnalyzer.java:
(analyzeCode): handle empty blocks.
2001-08-14 Jochen Hoenicke <jochen@gnu.org>
* build.xml: test is default.
(release-javadoc): New target.
(release-src): Get from dir test only source files.
(doc-javadoc): More parameters for nicer docu.
2001-08-12 Jochen Hoenicke <jochen@gnu.org>
* net/sf/jode/bytecode/TypeSignature.java:
(getArgumentSize): Renamed to ...
(getParameterSize): ... this. Changed all callers.
(skipType): Made private.
* net/sf/jode/jvm/CodeVerifier.java:
(initInfo): Use TypeSignature.getParameterTypes instead of skipType.
* net/sf/jode/jvm/SyntheticAnalyzer.java:
(checkGetClass): Be more lenient with the types, they are already
checked by the CodeVerifier. This is to support jdk-1.4.
* net/sf/jode/expr/InvokeOperator.java
(dumpExpression): Fixed the check for null outerExpr.
* net/sf/jode/flow/FlowBlock.java:
(checkConsistent): Allow lastModified in a finally block.
* net/sf/jode/flow/TransformExceptionHandlers.java: Reworked exception
handlers again. This time checked with javac 1.3, javac 1.1 and
jikes.
(checkTryCatchOrder): New method that was previously part of
analyze.
(analyze): Use checkTryCatchOrder. Don't merge try and catch flow
blocks anymore, leave it to the analyzeXXX methods.
(mergeTryCatch): New method.
(analyzeCatchBlock): Get catchFlow as parameter. Call
mergeTryCatch.
(transformSubroutine): Handle POP-only subroutines.
(removeJSR): Don't do special case for catchBlock any more. This
is because catchFlow isn't yet merged when this method is called.
(checkAndRemoveJSR): Likewise.
(checkAndRemoveMonitorExit): Likewise. Merge subroutine only if
we are the only predecessor.
(analyzeSynchronized): Get catchFlow as parameter. Call
mergeTryCatch.
(mergeFinallyBlocks): New method, calls mergeTryCatch and does the
common part of mergeFinally and mergeSpecialFinally.
(analyzeFinally): Simplified, after checking and removing JSR, it
does immediately analyze and transform subroutine to get the
finallyBlock. Then it throws away the catchFlow and calls
mergeFinallyBlocks.
(analyzeSpecialFinally): Simplified, after checking it only handles
the jumps in the try part and then call mergeFinallyBlocks.
2001-08-08 Jochen Hoenicke <jochen@gnu.org>
More Documentation updates.
* build.xml: Release rules.
* scripts/jcpp.pl: Don't make backups of original.
* net/sf/jode/bytecode/BasicBlocks.java (setBlocks): Check that
successors are inside method.
* net/sf/jode/bytecode/Block.java (getStackHeight): New Method.
* net/sf/jode/bytecode/ClassPath.java (Location): public class to
model a component of the class path. Previously it was Path.
(ClassPath): New constructors added that take Location objects.
* net/sf/jode/bytecode/ConstantPool.java (getClassName): Cache
constants.
* net/sf/jode/bytecode/GrowableConstantPool.java: Made public.
(grow): Check that not too many constants are added.
(reserveLongConstants): Removed (not used).
(copyConstant): Removed (not used).
* net/sf/jode/jvm/NewObject.java: Made package protected.
* net/sf/jode/obfuscator/modules/RemovePopAnalyzer.java:
Big updates (almost rewrote from scratch). Still doesn't compile.
2001-08-05 Jochen Hoenicke <jochen@gnu.org>
Documentation updates (INSTALL, javadoc).
Added JUnit Test cases.
* build.xml: Big update.
* net/sf/jode/bytecode/BasicBlock.java:
(updateMaxStackLocals): new method to calculate maxStack and
maxLocals.
(setBlocks): fixed calculation of handlers, call updateMaxLocals.
* net/sf/jode/bytecode/BasicBlockReader.java:
(maxLocals, maxStack): new fields.
(readCode): read maxStack/Locals into private fields.
(convert): check that maxStack/Locals match what we calculate.
* net/sf/jode/bytecode/BinaryInfo.java:
(getKnownAttributeCount): renamed to...
(getAttributeCount): ... this, and also count internal attributes.
Made it protected.
(readAttribute): made protected.
(drop): made protected.
(prepareAttributes): made protected.
(writeKnownAttributes): removed.
(writeAttributes): made protected, use getAttributeCount.
Changed policy: it doesn't call writeKnownAttribute, but instead
it expects sub classes to override this method.
(getAttributeSize): made protected, subclasses should override it.
Changed all subclasses to new policy.
* net/sf/jode/bytecode/Block.java:
(lineNr): Removed, it wasn't used.
(pop,push): Removed, replaced by ...
(maxpop,maxpush,delta): ... these, with slightly changed semantics.
(stackHeight): New variable.
(Block): Default Constructor doesn't initialize fields now.
(getCatchers): Renamed to ...
(getHandlers): ... this, changed all callers.
(initCode): Calculate maxpop, maxpush, delta correctly.
(getStackPopPush): Changed accordingly to new fields.
(setCode): Removed debugging output for illegal contents.
* net/sf/jode/bytecode/Classes.java: Reworked handling of inner
classes.
(innerClasses): Field mustn't be null anymore when loaded.
(setName): Update class in classpath.
* net/sf/jode/bytecode/ClassPath.java:
(renameClassInfo): new function, should only used by ClassInfo.
* net/sf/jode/bytecode/ConstantPool.java: made public.
(getUTF8,getRef,getClassType,getClassName): Don't allow the 0 index.
(iterateClassNames): New method.
* net/sf/jode/decompiler/Main.java:
(decompileClass): Catch ClassFormatExceptions and decompile
remaining classes.
* net/sf/jode/obfuscator/ClassIdentifier.java:
Updated handling of inner/extra classes to new ClassInfo behaviour.
(initSuperClasses): Load DECLARATION of super classes.
* net/sf/jode/obfuscator/PackageIdentifier.java:
Replace deprecated methods of ClassInfo with corresponding classpath
calls.
(loadMatchingClasses): Initialize packages loaded on demand if we
are initialize.
* net/sf/jode/obfuscator/modules/ConstantAnalyzer.java:
Now extends SimpleAnalyzer.
(canonizeIfaceRef): Removed; it is now inherited.
(canonizeRef): likewise.
Big updates to handle jsr correctly.
(handleOpcode): Moved method to BlockInfo.
* net/sf/jode/obfuscator/modules/SimpleAnalyzer.java:
(canonizeIfaceRef): New method, copied from ConstantAnalyzer.
(canonizeRef): call canonizeIfaceRef for interfaces.
* net/sf/jode/util/UnifyHash.java
(iterateHashCode): iterator now supports remove().
(remove): New method.
2001-07-30 Jochen Hoenicke <jochen@gnu.org>
Changed compilation procedure to ant.
2001-07-30 Jochen Hoenicke <jochen@gnu.org>
* jode/bytecode/BasicBlockReader.java: Fixed import of non
collection java.util classes.
* jode/bytecode/BasicBlockWriter.java: likewise.
2001-07-28 Jochen Hoenicke <jochen@gnu.org>
* jode/AssertError.java: removed, all uses are now replaced
by java.lang.InternalError.
* jode/Makefile.am: removed AssertError.java
* jode/bytecode/ClassInfo.java: reworked handling of inner
classes.
(extraClasses): removed, they are calculated automatically.
(hasInnerClassesAttr): new variable.
(readInnerClassesAttribute): Mark all classes in the constant
pool as having OUTERCLASS info filled. Don't handle extraClasses
specially.
(prepareWriting): Change for automatically generating outer
class info.
(getKnownAttributes): dito.
(writeKnownAttributes): dito.
(getExtraClasses): removed.
(setExtraClasses): removed.
* jode/bytecode/ClassAnalyzer.java (conflicts): load or guess
declarations of info before getting inner classes.
* jode/decompiler/TabbedPrintWriter.java (BreakPoint.endOp):
Set options correctly.
* jode/expr/InvokeOperator.java (getMethodInfo): load or guess
declarations before accessing methods.
* jode/flow/FlowBlock.java (resolveSomeJumps): When creating a
if-then-else move the jump from the then branch to the if, before
restarting analysis.
(doT1): handle the case when lastModified.jump is null. Throw
statements have no jump now.
* jode/jvm/SyntheticAnalyzer (checkAccess): Fix the detection for
PUTDUPSTATIC/FIELD.
* jode/type/ClassType.java (getCastHelper): More checks when
cast is not needed: interfaces and null pointer.
2001-07-15 Jochen Hoenicke <jochen@gnu.org>
* jode/decompiler/Decompiler.java (decompile): removed
setClassPath call. ClassInfo.forName() is no longer used.
* jode/decompiler/Main.java (decompile): likewise.
2001-07-15 Jochen Hoenicke <jochen@gnu.org>
Applied patches from 2001-05-26 of Jode 1.1 tree:
* configure.in: Set version to 1.1.
* jode/swingui/Main.java (main): Also use bootclasspath if no
classpath given.
* jode/decompiler/MethodAnalyzer.java (skipWriting): Don't skip
empty constructor that have a throws clause.
* configure.in: Determine whether jdk1.1 resp. jdk1.2. Call jcpp
in config.status.
* jode/expr/Expression.java (makeInitializer): Now takes the
type of the initialization. Changed all callers.
* jode/expr/ConstantArrayOperator.java (makeInitializer): Check
that type is our array type, otherwise we can't omit new Array[].
* jode/decompiler/LocalInfo.java (markFinal): Don't check that
only one write is present. If two writes are in an then and an
else branch of an if, the local can still be final.
* jode/type/ArrayType.java (getSubType): Handle array of integer
types correctly: byte[] is something completely different than
int[].
(getSuperType): Likewise.
* jode/expr/FieldOperator.java (getFieldInfo): New function.
(needsCast): A cast is also needed if the field is private or
package scope and the current type can't access the field.
* jode/expr/InvokeOperator.java (getMethodInfo): New function.
(needsCast): A cast is also needed if the method is private or
package scope and the current type can't access the method.
* jode/expr/ArrayStoreOperator.java (dumpExpression): Check if a
cast of the array expression is needed.
* jode/expr/TransformConstructors.java
(transformFieldInitializers): Don't allow moving method invocations
that throw a checked exception.
* jode/bytecode/MethodInfo.java (readAttribute): Read Exceptions
attribute even when not all attributes should be read. They are
needed by TransformConstructors, see above.
* jode/decompiler/TabbedPrintWriter.java (saveOps): Don't allow
line breaks in not completed expressions since implicit parentheses
would destroy the syntax. No need to put line break option on stack.
(restoreOps): Adapted Stack format.
* jode/decompiler/ClassAnalyzer.java (dumpDeclaration): Moved
Code from dumpSource here. Don't put a line break after closing
brace.
(dumpSource): call dumpDeclaration and add a line break.
(dumpBlock): Moved dropInfo(ATTRIBS) here.
* jode/decompiler/ClassAnalyzer.java (STRICTFP): New Constant.
(isStrictFP): New function.
(initialize): Set strictfp modifier if a constructor has it set.
(dumpSource): Handle strictfp modifier.
* jode/decompiler/MethodAnalyzer.java (STRICTFP): New Constant.
(isStrictFP): New function.
(dumpSource): Handle strictfp modifier.
* jode/jvm/SyntheticAnalyzer.java (checkAccess): Check for a
special putfield access, where the set value is returned. Allow
the modifier of field/method to be protected and the class to be
a superclass.
(checkStaticAccess): Likewise.
(ACCESSDUPPUTFIELD): New Constant.
(ACCESSDUPPUTSTATIC): New Constant.
* jode/expr/InvokeOperator.java (simplifyAccess): Handle new
synthetics.
* jode/flow/SpecialBlock.java (removePop): Remove pop also for
non void store instructions.
* jode/decompiler/MethodAnalyzer.java (skipWriting): Also skip
the new synthetics.
* jode/decompiler/Main.java (main): Call System.exit() after
everything was compiled.
* jode/flow/TransformExceptionHandlers.java (removeJSR):
Renamed back from removeBadJSR (see patch from 2001-02-04). The
checkAndRemove* functions mustn't change the successors while they
iterate over them. Instead of removing good jsr they mark them as
good and removeJSR will finally remove them.
(checkAndRemoveJSR): See above.
(checkAndRemoveMonitorExit): See above.
* jode/flow/JsrBlock.java (good): New variable, see above.
(setGood): New method.
(isGood): New method.
2001-07-15 Jochen Hoenicke <jochen@gnu.org>
Applied patch from 2001-05-08 of Jode 1.1 tree:
* jode/jvm/CodeVerifier.java (doVerify): Don't check for
uninitialized objects in local or stack slots on backwards jump or
exception blocks. Sun's jdk also doesn't check it, and I never
understood why it is necessary. But see JVM Spec 4.9.4.
2001-07-15 Jochen Hoenicke <jochen@gnu.org>
Applied patch from 2001-05-02 of Jode 1.1 tree:
* jode/obfuscator/modules/ConstantAnalyzer.java (handleOpcode):
Added divide by zero checks for opc_irem and opc_lrem.
2001-07-15 Jochen Hoenicke <jochen@gnu.org>
Applied patches from 2001-02-27 of Jode 1.1 tree:
* acinclude.m4 (JODE_CHECK_CLASS): Changed "test -e" to "-f" since
-e is not supported on all architectures (Solaris) and -f is more
correct anyway.
Reported by Erik Modén.
* jode/swingui/Main.java (AreaWriter): Convert all kinds of
line breaks (CR+LF, CR, LF) to a LF character, which a JTextArea
understands.
2001-07-15 Jochen Hoenicke <jochen@gnu.org>
Applied patch from 2001-02-04 of Jode 1.1 tree:
* jode/expr/IfThenElseOperator.java (simplify): Allow in the class$
simplification the then and else part to be swapped.
* jode/type/ClassType.java (keywords): Added the package
and import keywords.
* jode/flow/TransformExceptionHandlers.java:
(getPredecessor): New function.
(getMonitorExitSlot): New function.
(skipFinExitChain): New function.
(removeJSR): Replaced by ...
(removeBadJSR): ... this.
(checkAndRemoveJSR): Use the new functions. Much simpler and
handles nested synchronized blocks. It now traces the whole JSR
and monitorexit chain before a jump to the first entry via
skipFinExitChain, then checks and remove the first JSR
resp. monitorexit. JSR jumps are simply ignored now.
(checkAndRemoveMonitorExit): likewise.
* jode/flow/StructuredBlock.java (prependBlock): New function.
* jode/flow/CatchBlock.java (makeDeclaration): Generate name
of dummyLocal, since nobody else will generate it.
* jode/bytecode/BasicBlockReader.java (readCode): Remove bogus
exceptionHandlers, whose catchers just throw the exception again.
This kind of entries are inserted by an obfuscator and would break
JODE.
* jode/util/UnifyHash.java (iterateHashCode): Call cleanUp,
to clean unneeded references.
* jode/flow/TransformConstructors.java (transformOneField):
Changed to private. Take field number as parameter. Check that
expression doesn't contain a FieldOperator for a later field of
the same class or a PutFieldOperator. Changed all callers.
2001-07-15 Jochen Hoenicke <jochen@gnu.org>
Applied patch from 2001-02-01 of Jode 1.1 tree:
* jode/jvm/CodeVerifier.java (Type.mergeType): If array elem
types can't be merged, return tObject as common super type.
* jode/type/ArrayType.java (getGeneralizedType): If array elem
type can't be intersected, return tObject as common super type.
2001-07-15 Jochen Hoenicke <jochen@gnu.org>
Applied patch from Jode 1.1 tree:
* jode/expr/Expression.java (updateParentTypes): Call setType,
instead of merging the types. Other childs want to know about the
type change as well.
* jode/decompiler/LocalInfo.java (combineWith): Reorganized a bit,
but no changes.
* jode/expr/InvokeOperator.java (dumpExpression): Always print
the ThisOperator if a field is from a parent class of an outer
class is used. And always qualify the this operator if not
innermost.
2001-07-14 Jochen Hoenicke <jochen@gnu.org>
Applied patches from the Jode 1.1 tree:
* jode/decompiler/TabbedPrintWriter.java: Better gnu style handling:
(openBraceClass) (closeBraceClass)
(openBraceNoIndent) (closeBraceNoIndent): new functions.
(closeBraceNoSpace): Removed.
* jode/decompiler/TabbedPrintWriter.java (GNU_SPACING): new constant.
(printOptionalSpace): Print space for GNU_SPACING.
* jode/decompiler/Options.java (setOptions): changed gnu style
to include GNU_SPACING.
* jode/decompiler/ClassAnalyzer.java (dumpSource): Use
open/closeBraceClass.
* jode/decompiler/MethodAnalyzer.java (dumpSource): Use
open/closeBraceNoIndent. Call printOptionalSpace.
* jode/decompiler/InvokeOperator.java (dumpExpression):
Call printOptionalSpace, use open/closeBraceClass for inner
classes.
* jode/decompiler/UnaryOperator.java (dumpExpression): Call
printOptionalSpace.
Added pascal style from Rolf Howarth <rolf@squarebox.co.uk>
* jode/decompiler/Decompiler.java (setOption): detect pascal option.
* jode/decompiler/TabbedPrintWriter.java (BRACE_FLUSH_LEFT):
new constant.
(openBrace, openBraceContinue, closeBrace, closeBraceNoSpace,
closeBraceContinue): handle flush left.
* jode/type/NullType.java (intersection): Removed, since the
version in ReferenceType is more correct. Before
tNull.isOfType(tRange(X,tNull)) returned false, which lead to
incorrect behaviour in InvokeOperator.needsCast.
* jode/decompiler/FieldAnalyzer.java (dumpSource): Removed the
"= null" hack for final fields; it was not correct, since the
field could be initialized in a constructor.
* jode/decompiler/TabbedPrintWriter.java (BreakPoint.endOp):
Simplified the code, copy options always from child.
* jode/expr/InvokeOperator.java (isGetClass): Allow the method to
be declared inside an outer class: We simply check if we can get
the method analyzer.
(simplify): handle unifyParam.
* jode/expr/PopOperator.java (getBreakPenalty): return penalty of
inner expression. (dumpExpression): Call dumpExpression of
subexpression immediately without priority.

@ -1,23 +1,33 @@
Before installing, make sure you have at least version 1.1 of the java
developement kit installed. If you want to run this program you only
need the java runtime environment. Version 1.1 is quite old, I
recommend using Java 2 (jdk1.2 or above). You need perl if you want
to compile a 1.1 version.
This package was designed to use the ANT from the jakarta.apache.org
tools. I assume you have installed it correctly.
Take some time to edit config.props. There are a few options you need
to take care of. (Unfortunately ant can't test for executables).
Now you are ready to invoke ant. There are many possible targets, here
are the most useful ones:
all builds class files and documentation.
build builds class files only (autodetects java version).
build-1.1 builds JDK1.1 class files.
doc builds documentation.
dist creates all release files.
test does some self tests. You need to have junit installed for this.
clean cleans everything that doesn't belong to the source distribution.
cvsclean cleans everything that doesn't belong into the cvs repository.
Before installing, make sure you have a java compiler (e.g javac or
jikes) and the java 1.1 runtime class library installed. If you want
to run this program you need at least a 1.1 compatible java virtual
machine. There are some bugs in javac included in the SUN JDK 1.1, it
won't work.
This package was designed to use the GNU standard for configuration
and makefiles. To build and install do the following:
0). Make sure that you have all libraries that are needed in you
classpath. You need gnu.getopt, and if you have JDK 1.1 you also need
the collection classes and swing for 1.1.
1). Run "aclocal && autoconf && automake --add-missing".
2). Run the "configure" script to configure the package. There are
various options you might want to pass to configure to control how the
package is built. "configure --help" will give a complete list.
If you have jikes, you should specify it with --with-jikes. You can
give a path to the directory where it resides, otherwise it is
searched in the path.
3). Type "make" to build the package. If you don't have jikes, you
should make clean first, since the dependency problem is not yet
resolved.
4). Type "make install" to install everything. This doesn't work yet.
The created jar file is stored in the share directory.
Jochen

@ -1,3 +0,0 @@
Manifest-Version: 1.0
Main-Class: net.sf.jode.swingui.Main
Created-By: SeeksTheMoon

@ -0,0 +1,5 @@
## Input file for automake to generate the Makefile.in used by configure
SUBDIRS = jode bin doc test
EXTRA_DIST = TODO

@ -1,35 +1,9 @@
New in 1.2
* New bytecode interface
* Faster and better flow analyzation
New in 1.1
* break long lines
* handle most of javac v8 constructs (jdk 1.3)
* bug fixes
New in 1.0.93
* anonymous and inner class decompilation reworked.
* replaced a bash specific construct in acinclude.m4
* fixed a funny bug: string += "1" was decompiled as string++
* main class of decompiler is now jode.decompiler.Main
* fixed a bug in ConstantAnalyzer (obfuscator) (produced wrong code)
* fixed more bugs in obfuscator
* better memory usage in decompiler
* fixed a bug in decompiler (couldn't handle nop instruction)
* web pages updated.
New in 1.0.92
* option --pretty works again
* web pages updated
* swingui can show class hierarchie
* KeywordRenamer added to obfuscator.
New in 1.0.91:
* first version using configure. Jode can now be almost automatically
1.0.90 is a prerelease..
* First version using configure. Jode can now be almost automatically
build, see INSTALL for instructions.
* the decompiler can handler inner and anoymous classes.
* you now need the gnu getopt package.
* you need JDK 1.2 or alternatively the swing and collection packages
* The decompiler can handler inner and anoymous classes.
* You now need the gnu getopt package.
* You need JDK 1.2 or alternatively the swing and collection packages
for 1.1

@ -1,90 +1,106 @@
JODE (Java Optimize and Decompile Environment)
takes class-files as input and produces something similar to the
original java-File. Of course this can't be perfect: There is no way
to produce the comments or the names of local variables (except when
compiled with <code>-g</code>) and there are often more ways to write
the same thing. But it does its job quite well.</P>
<h2>Quick Test</h2>
I have now an applet interface to the decompiler.
<a href="jode-applet.html">Check it out</a>.
<h2>How to get it</h2>
<P>You can donwload the files in zip form.
The <a href="jode_src.zip">sources</a> contain only the
<code>java</code> files, the <a href="jode_cls.zip">classes</a>
contain only the <code>class</code> files. </p>
<p>I also have a <a href="jode.tar.gz">tar.gz file</a> containing only
the <code>RCS</code> directories. This is the form I maintain the
project, but you probably need unix and a few tools to use them.</p>
<p>There are also some <a href="snapshot/">snapshots</a> that have new
features like inner and anonymous classes. </p>
<p><a href=".">Click here</a> to browse the files online.
</p>
<h2>How to use it</h2>
<p>I have some simple step by step pages. There are three
possibilities:
<ul>
<li> <a href="jode-useapplet.html"> Using the applet version</a>.
This can make problem due to java's security policy, but is the
simplest way and works on most platforms.
</li>
<li> If you use Windows, you should look on <a
href="jode-win.html">this page</a>.</li>
<li> Unix users should look on <a href="jode-unix.html">this page</a>.
</ul>
<h2>Known bugs</h2>
<p>There may be situations, where the code doesn't understand complex
expressions. In this many ugly temporary variables are used, but the
code should still be compileable. This does especially happen when
you compile with `-O' flag and javac has inlined some methods. </p>
<p>Sometimes this program may exit with an <code>Exception</code> or
produce incorrect code. Most time the code can't be compiled, so that
it can be easily spotted. If you have one of these problems (except
those that occur on some of the <code>jode.test</code> files, I would
be very interested in a bug report (including the <code>class</code>
file, if possible).</p>
<p>Sometimes it generates some <code>GOTO</code> expression and
labels. This can't be compiled, but shouldn't happen any more with
javac or jikes.</p>
<p>It doesn't handle inner and anonymous classes, yet. You can
decompile them separately, though (use `<code>+$</code>' switch under
jikes), but there is a bug in javac, so that a final variable is twice
initialized. If you encounter this problem just remove the doubled
line by hand. </p>
<p><b>New!</b> The latest <a href="snapshot">snapshot</a> can handle
inner and anonymous classes.</p>
<h2>Why did I wrote it?</h2>
<p>Someday I found <code>guavad</code>, a disassembler for java byte
code (it does similar things like <code>javap&nbsp;-c</code>). I used
it on a class file, and found that it was possible to reconstruct the
original java code. First I did it by hand on some small routines,
but I soon realized that it was a rather stupid task, and that I could
write a <a href="../perl/dasm_to_java.perl"><code>perl</code> script</a>
that does the same. At the end of the next day I had a working
decompiler.</p>
<p>Now while it was working, it was not easy to use. You had to
decompile the code first with a disassembler, cut the method, you
wanted to decompile and then run the perl script on it. So I decided
to get some information of the class files and do this all
automatically. I decided to write it in <code>java</code> now,
because it suited best.</p>
<p>Just for the records: the java code is now more than 50 times
bigger than the original perl script and is still growing.</p>
<h2>License</h2>
<p>This code is under GNU GPL. That basically means, that you can copy
or modify this code, as long as you put all your modification under
the GPL again. <A HREF="http://www.gnu.org/copyleft/gpl.html"> Look
here for the complete license</a>.</p>
<hr>
<p><A HREF="mailto:Jochen.Hoenicke@Informatik.Uni-Oldenburg.DE">
http://www.informatik.uni-oldenburg.de/~delwi/jode/jode.html</A>, last
updated on <em>17-Jun-1999</em>.</p>
JODE is a java package containing a decompiler and an optimizer for
java. This package is freely available under the GNU General Public
License.
The decompiler reads in class files and produces something similar to
the original java file. Of course this can't be perfect: There is no
way to produce the comments or the names of local variables (except
when the java files were compiled with `-g') and there are often more
ways to write the same thing. However, jode does its job quite well.
The optimizer transforms class files in various ways with
can be controlled by a script file.
Please note that most software licenses forbid to decompile class
files. Use this decompiler only, if you have legal rights to
decompile the class (e.g. on your own code).
The features of the decompilers are:
* Systematic flow analysis, that can decompile every java code
without the need of goto (which doesn't exists in java).
* Type deduction, that can guess the type of local variables, even if
it is an interface type that doesn't occur in the bytecode.
* Handling of inner and anonymous classes.
* Different indentation styles available.
* It can decompile itself (194 classes) without a single error.
* It can decrypt strings on the fly, that were encrypted by an obfuscator.
Known bugs of the decompiler:
- Some jdk1.3 synthetic access functions aren't understood. The
produced source contains access$xxx functions, but it still compiles.
- There may be other bugs, that cause Exceptions or invalid code.
If you have such a problems don't hesitate to issue a bug report.
Please include the <code>class</code> file if possible.
Limitations:
- If not all dependent classes can be found, the verifier (which is
run before decompilation starts) may exit with a type error. You
can decompile it with --verify=off, but take the warning serious,
that the types may be incorrect. There's sometimes no way to guess
the right type, if you don't have access the full class hierarchie.
But if you don't have the dependent classes, you can't compile the
code again, anyway, so why do you want to decompile it?
- There may be situations, where jode doesn't understand complex
expressions. In this case many ugly temporary variables are used,
but the code should still be compileable. This does especially
happen when you compile with `-O' flag and javac has inlined some
methods.
The features of the obfuscator are:
* Modular design, you can plug the obfuscation transformation you need
together via the script file.
* Strong analysis, that optimizes away fields, expressions that are
known to be constant (and reverts the flow obfuscation of Zelix
Klassmaster)
* Can also be used as Optimizer, without any obfuscation at all, it
will preserve the local variable table and line number table.
* Many different renaming options, you can also simply add your own.
PRELIMINARIES:
See INSTALL for installation instructions.
USAGE:
First set the classpath. It should contain the jar file jode-1.1.jar,
the gnu getopt package and the sun collection package for 1.1. For
the swingui program you also need swing in you classpath.
You can then decompile a class file with:
java jode.decompiler.Main --classpath program.jar,libfoo.jar org.package.Class
or a complete package with
java jode.decompiler.Main --classpath libfoo.jar program.jar
For a graphical user interface based on swing try:
java jode.swingui.Main --classpath jarfile1.jar
The obfuscator/deobfuscator can be run with a script:
java jode.obfuscator.Main obfuscation.jos
See the web documents for more information about the script syntax.
</body>
</html>

@ -1,5 +0,0 @@
Joe Bronkema <joseph.d.bronkema at lmco.com>
Rolf Howarth <rolf at squarebox.co.uk> for pascal indentaton style.
Erik Modén <Erik.Moden at emw.ericsson.se>
Martin Schmitz <m.schmitz at e-sign.com> for finding many bugs in the obfuscator.
zzzeek <classic at io.com>

@ -1,64 +1,28 @@
This is a list of features, that would be nice to have:
Decompiler:
- BUG: public final static null fields aren't initialized (leads to compile error)
- outline inlined methods.
- deinline inlined methods.
- remove string decrypt method.
- remove synthetic methods if and only if all calls to them are resolved.
- rename keywords to safe names.
~ handle try catch more thouroughly/safely.
~ decompile jode.jvm.Interpreter (hand optimized bytecode)
Obfuscator:
- Detect Class.forName() calls with constant parameters and rename
these constants. Detect class$ methods with constant parameters.
Warn about all other occurences of Class.forName()
- work around Class.forName, by creating a new version using a hash
table that maps md5 sums of old names to obfuscated names.
This should be put into the constant analyzer. The simple
analyzer should only do the warnings.
- Transforming the class hierarchy, e.g. combining two totally
unrelated classes together into one class or make some class
to implement some interfaces, that it previously didn't.
- Doing flow obfuscation, i.e. do some tests, that one knows to
succeed always, and jump to funny position if the test fails.
The tests should use undecidable properties, so that a
deobfuscator cannot remove them again.
- read options from a script.
- flow obfuscation/optimization.
- warn about Class.forName and list occurences.
DeObfuscator:
- Deobfuscator should detect inner/anonymous classes and mark them
as such. It should be possible with the renaming table to mark
inner classes as well. Inner classes are easy to detect; there
constructor has a special form. And the information is very
useful for the decompiler.
This should be done with some generalize interface similar to (or
instead of) Transformer
- Deobfuscator should generate nicer names. This should be a
special Renamer. The renamer should analyze short methods and
call them getXXX, isXXX, setXXX if apropriate, detect synthetic
methods and similar. Class names should be derived from super
class or interface (e.g. Enumeration), fields should be derived
from their type, maybe also from their assignments.
One can build more renamer, each handles some special cases and
calls the next one, if it can't handle an identifier.
- generate nice names:
- classes: derive name from super.
- fields: derive name from type.
- give synthetic methods the right attribute and name (e.g. class$)
- detect inner classes and give suitable names.
User Interface:
- make a nice user interface:
~ list classnames: toggable between class hierarchie/package hierarchie.
- list classnames: toggable between class hierarchie/package hierarchie.
- list fields/method of selected class.
- show decompilation of selected method.
- show usage of method/fields.
- syntax highlighting, hyper links etc.
(look at java.swing.JEditorPane or at Java Insight)
- as a first approximation use HTML code and a JHTMLPane
- visual obfuscation/deobfuscation (like klassmaster?, better?)
Internal:
- clean up package hierarchy, esp. expr, flow and decompiler.
- move to net.sf.jode package.
- make the class names more precise, e.g. StructuredBlock is Statement,
FlowBlock is BasicBlock.

@ -0,0 +1,44 @@
dnl
dnl Add macros
dnl JODE_CHECK_JAVA
dnl
dnl JODE_CHECK_JAVA(path)
AC_DEFUN(JODE_CHECK_JAVA,
[
AC_PATH_PROG(JAVA, java, "", $1/bin:$1/jre/bin:$PATH)
AC_PATH_PROG(JAVAC, javac, "", $1/bin:$PATH)
AC_PATH_PROG(JAR, jar, "", $1/bin:$PATH)
for path in $1/lib $1/jre/lib $1/shared; do
for classlib in classes.zip rt.jar; do
AC_CHECK_FILES($path/$classlib,
[ CLASSLIB=$path/$classlib
break 3
], [ true ])
done
done
AC_SUBST(CLASSPATH)
AC_SUBST(CLASSLIB)
])
AC_DEFUN(JODE_CHECK_CLASS,
[
if (IFS=":"
clazz=`echo $1 | sed -e 's/\./\//g' -e 's/\(.*\)/\1.class/'`
jode_found=0
for path in $2; do
if test -d $path; then
if test -e $path/$clazz; then
exit 0
fi
elif $UNZIP -v -C $path $clazz &>/dev/null ; then
exit 0
fi
done;
exit 1)
then
$3
else
$4
fi
])

@ -23,37 +23,22 @@
for (@ARGV) {
my $file = $_;
$file =~ m=([^/]*)\.java(\.in)?$= or do {
$file =~ m=([^/]*)\.java$= or do {
print STDERR "$file is not a java file";
next;
};
my $class = $1;
my $curyear = `date +%Y`;
chomp $curyear;
# my $firstcheckin = `rlog $file 2>/dev/null |grep date| tail -1`;
# my $firstyear =
# ($firstcheckin =~ m=date: ([0-9]+)/[0-9]+/[0-9]+=) ? $1 : $curyear;
my $firstcheckin = `rlog $file 2>/dev/null |grep date| tail -1`;
my $firstyear =
($firstcheckin =~ m=date: ([0-9]+)/[0-9]+/[0-9]+=) ? $1 : $curyear;
# my $lastcheckin = `rlog $file 2>/dev/null |grep date| head -1`;
# my $lastyear =
# ($firstcheckin =~ m=date: ([0-9]+)/[0-9]+/[0-9]+=) ? $1 : $curyear;
open FILE, "<$file";
while (<FILE>) {
$firstyear = $1 if /Copyright \(C\) (\d{4})/;
last if /^package/;
}
$firstyear = $curyear if ! $firstyear;
my $lastyear = $curyear;
my $years = ($firstyear == $lastyear)
? $firstyear : "$firstyear-$lastyear";
my $lesser = "";
my $dotlesser = "";
if ($file =~ m!jode/(util|bytecode|jvm|flow|expr|decompiler
|GlobalOptions|AssertError)!x) {
$lesser = " Lesser";
$dotlesser = ".LESSER";
}
rename "$file", "$file.orig" or do {
print STDERR "Can't open file $file\n";
@ -65,7 +50,7 @@ for (@ARGV) {
/* $class Copyright (C) $years Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU$lesser General Public License as published by
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
@ -74,8 +59,8 @@ for (@ARGV) {
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU$lesser General Public License
* along with this program; see the file COPYING$dotlesser. If not, write to
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* \$Id\$

@ -1,5 +1,4 @@
## Input file for automake to generate the Makefile.in used by configure
bin_SCRIPTS = jode
EXTRA_DIST = jode.bat.in jode.in
bin_SCRIPTS = jode

@ -1,19 +0,0 @@
; Use this batch file to make invoking the decompiler easier.
; Please edit this file and insert correct directories where needed.
;
; Usage: jode dec [decompiler options]
; jode swi [swingui options]
; jode obf [obfuscator options]
; Since the decompiler is the most important program you can omit `dec':
; jode [decompiler options]
set CLASSPATH=jode-@VERSION@-1.2.jar;%CLASSPATH%
set PROGGY=default
if %1 == swi set PROGGY=swingui
if %1 == obf set PROGGY=obfuscator
if %1 == dec set PROGGY=decompiler
if NOT %PROGGY% == default shift
if %PROGGY% == default set PROGGY=decompiler
java jode.%PROGGY%.Main %1 %2 %3 %4 %5 %6 %7 %8 %9

@ -3,9 +3,9 @@ prefix=@prefix@
case $1 in
[Ss]wi*) CLAZZ=jode.swingui.Main; shift ;;
[Dd]ec*) CLAZZ=jode.decompiler.Main; shift ;;
[Dd]ec*) CLAZZ=jode.Decompiler; shift ;;
[Oo]bf*) CLAZZ=jode.obfuscator.Main; shift ;;
*) CLAZZ=jode.decompiler.Main ;;
*) CLAZZ=jode.Decompiler ;;
esac

@ -1,380 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Jakarta-Ant build file for jode, Copyright (C) 1999-2004 Jochen Hoenicke.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$Id$
-->
<!DOCTYPE project PUBLIC "-//ANT//DTD project//EN" "project.dtd">
<project name="jode" default="test" basedir=".">
<!-- set global properties for this build -->
<property name="version" value="1.90-CVS"/>
<property name="build" value="${basedir}/build"/>
<property name="props" value="${basedir}/props"/>
<property name="doc" value="${basedir}/doc"/>
<property name="lib" value="${basedir}/lib"/>
<property name="src" value="${basedir}/src"/>
<property name="release" value="${basedir}/release"/>
<property name="distdir" value="${release}/jode-${version}"/>
<property name="scripts" value="${basedir}/scripts"/>
<property name="api.doc" value="${doc}/api"/>
<property name="test" value="${basedir}/test"/>
<property name="test.src" value="${test}/src"/>
<property name="test.build" value="${test}/build"/>
<property name="test.log" value="${test}/log"/>
<property name="jcpp" value="${scripts}/jcpp.pl"/>
<property name="versionfile" value="${src}/jode/GlobalOptions.java"/>
<property file="config.props"/>
<path id="project.classpath">
<pathelement path="${classpath}"/>
<fileset dir="lib" includes="*.jar"/>
</path>
<!-- ********* General targets ******* -->
<!-- compiles jode and creates its javadoc-files -->
<target name="all" depends="build,doc"/>
<!-- clean all -->
<target name="clean" depends="clean-jcpp,clean-build,clean-doc,clean-test"/>
<target name="cvsclean" depends="clean,clean-html,clean-release"/>
<!-- ********* jcpp targets ******* -->
<target name="check-jcpp" unless="perl.present">
<fail message="need perl to configure for JDK 1.1"/>
</target>
<target name="run-jcpp" depends="check-packages,check-jcpp">
<apply dir="." executable="perl" parallel="true">
<arg file="${jcpp}"/>
<arg value="-DJDK11"/>
<arg value="-DCOLLECTIONS=${collections.package}"/>
<arg value="-DCOLLECTIONEXTRA=${collections.package}"/>
<arg value="-DJAVAX_SWING=${swing.package}"/>
<fileset dir="${src}" includes="**/*.java"/>
</apply>
</target>
<target name="clean-jcpp" if="perl.present">
<apply dir="." executable="perl" parallel="true">
<arg file="${jcpp}"/>
<arg value="-DJDK12"/>
<arg value="-DCOLLECTIONS=java.util"/>
<arg value="-DCOLLECTIONEXTRA=java.lang"/>
<arg value="-DJAVAX_SWING=javax.swing"/>
<fileset dir="${src}" includes="**/*.java"/>
</apply>
</target>
<!-- ********* Check Environment ******* -->
<target name="check-jdk" unless="jdk1.1.forced">
<available property="jdk1.2+" classname="java.lang.ThreadLocal" />
<available property="jdk1.3+" classname="java.lang.StrictMath" />
</target>
<target name="fail-getopt" unless="getopt.present">
<fail message="Package gnu.getopt not found!"/>
</target>
<target name="check-getopt">
<available property="getopt.present"
classname="gnu.getopt.Getopt"
classpathref="project.classpath" />
<antcall target="fail-getopt"/>
</target>
<target name="check-packages">
<available property="collections.package"
value="gnu.java.util.collections"
classname="gnu.java.util.collections.Set"
classpathref="project.classpath" />
<available property="collections.package"
value="org.gnu.java.util.collections"
classname="org.gnu.java.util.collections.Set"
classpathref="project.classpath" />
<available property="collections.package"
value="com.sun.java.util.collections"
classname="com.sun.java.util.collections.Set"
classpathref="project.classpath" />
<available property="swing.package" value="com.sun.java.swing"
classname="com.sun.java.swing.JFrame"
classpathref="project.classpath" />
<available property="swing.package" value="javax.swing"
classname="javax.swing.JFrame"
classpathref="project.classpath" />
</target>
<!-- ********* Build targets ******* -->
<target name="preconfig" depends="check-jdk,check-getopt,preconfig.11"/>
<target name="preconfig.11" unless="jdk1.2+">
<antcall target="run-jcpp"/>
</target>
<target name="preconfig.12" if="jdk1.2+">
<antcall target="clean-jcpp"/>
</target>
<target name="build-1.1">
<antcall target="build">
<param name="jdk1.1.forced" value="on"/>
</antcall>
</target>
<target name="build" depends="check-jdk,preconfig">
<mkdir dir="${build}"/>
<javac srcdir="${src}"
destdir="${build}"
debug="true"
classpathref="project.classpath"
deprecation="on">
<exclude name="net/sf/jode/obfuscator/modules/RemovePopAnalyzer.java"/>
<exclude name="net/sf/jode/obfuscator/modules/LocalOptimizer.java"/>
<exclude name="net/sf/jode/obfuscator/modules/LocalizeFieldTransformer.java"/>
<!--
<exclude name="net/sf/jode/bytecode/*Subroutine*" />
-->
</javac>
</target>
<!-- clean the class files -->
<target name="clean-build">
<delete dir="${build}"/>
</target>
<!-- ********* Create Release files ******* -->
<target name="release" depends="release-bin,release-bin11,release-src,release-javadoc"/>
<target name="release-bindist" depends="build">
<jar jarfile="${distdir}/jode.jar" compress="true" manifest="${basedir}/MANIFEST.MF">
<fileset dir="${build}" includes="**/*.class"/>
<fileset dir="${props}" includes="**/*.properties"/>
</jar>
<copy todir="${distdir}">
<fileset dir="${lib}">
<include name="*getopt*.jar" />
<include name="*collection*.jar" unless="jdk1.2+" />
</fileset>
<fileset dir="${basedir}"
includes="AUTHORS,COPYING,NEWS,README,THANKS,TODO">
<include name="doc/*.html" />
<include name="doc/*.gif" />
<include name="doc/*.jos" />
<include name="doc/*.perl" />
</fileset>
</copy>
</target>
<target name="release-bin" depends="doc-html">
<antcall target="clean"/>
<mkdir dir="${release}"/>
<mkdir dir="${distdir}"/>
<antcall target="release-bindist"/>
<jar jarfile="${release}/jode-${version}.jar"
basedir="${release}" includes="jode-${version}/**"/>
<delete dir="${distdir}"/>
<antcall target="clean"/>
</target>
<target name="release-bin11" depends="doc-html">
<antcall target="clean"/>
<mkdir dir="${release}"/>
<mkdir dir="${distdir}"/>
<antcall target="release-bindist">
<param name="jdk1.1.forced" value="on"/>
</antcall>
<jar jarfile="${release}/jode-${version}-JDK1.1.jar"
basedir="${release}" includes="jode-${version}/**"/>
<delete dir="${distdir}"/>
<antcall target="clean"/>
</target>
<target name="release-src" depends="doc-html">
<antcall target="clean"/>
<mkdir dir="${release}"/>
<mkdir dir="${distdir}"/>
<copy todir="${distdir}">
<fileset dir="${basedir}"
includes="AUTHORS,COPYING,INSTALL,NEWS,README,THANKS,TODO,ChangeLog">
<include name="build.xml,config.props,project*.dtd"/>
<include name="doc/**"/>
<include name="scripts/**"/>
<include name="src/**"/>
<include name="test/*.java"/>
<include name="test/*.j"/>
<include name="test/src/**"/>
<include name="props/**"/>
<include name="lib/**"/>
</fileset>
</copy>
<jar jarfile="${release}/jode-${version}-src.jar"
basedir="${release}" includes="jode-${version}/**"/>
<delete dir="${distdir}"/>
</target>
<target name="release-javadoc">
<antcall target="doc-javadoc"/>
<mkdir dir="${release}"/>
<jar jarfile="${release}/jode-${version}-API.jar"
basedir="${doc}" includes="api/**"/>
<antcall target="clean-doc"/>
</target>
<target name="clean-release">
<delete dir="${release}"/>
</target>
<!-- ********* Javadoc targets ********** -->
<target name="doc" depends="doc-javadoc,doc-html"/>
<target name="doc-html" if="htp.present">
<apply executable="htp" dir="${doc}" dest="${doc}" parallel="false" relative="yes">
<arg value="-NODEPEND" />
<srcfile />
<targetfile />
<fileset dir="${doc}" includes="*.htp"/>
<mapper type="glob" from="*.htp" to="*.html"/>
</apply>
</target>
<target name="doc-javadoc">
<tstamp>
<format property="date" pattern="MMM d, yyyy"/>
</tstamp>
<mkdir dir="${api.doc}"/>
<javadoc packagenames="net.sf.jode.*"
windowtitle="Jode ${version} API Specification"
header='&lt;b&gt;&lt;a href="http://jode.sourceforge.net/"&gt;Jode&lt;/a&gt; ${version}&lt;/b&gt;&lt;br&gt;&lt;font size="-2"&gt;Build ${date}&lt;/font&gt;'
overview="${src}/net/sf/jode/overview.html"
bottom='Copyright &amp;copy; 1998-2004 by Jochen Hoenicke.'
sourcepath="${src}"
destdir="${api.doc}"
use="yes">
<link offline="${javadoc.offline}"
href="${javadoc.href}"
packagelistLoc="${javadoc.packagelistLoc}"/>
</javadoc>
</target>
<target name="clean-doc">
<delete dir="${api.doc}"/>
</target>
<target name="clean-html">
<delete>
<fileset dir="${doc}" includes="*.html"/>
</delete>
</target>
<!-- ********* test targets ************* -->
<target name="build-test" depends="build">
<mkdir dir="${test.build}"/>
<javac srcdir="${test.src}"
destdir="${test.build}"
debug="true"
classpathref="project.classpath"
classpath="${build}"
deprecation="on">
</javac>
</target>
<target name="test" depends="build-test">
<mkdir dir="${test.log}"/>
<junit printsummary="yes" fork="yes" haltonfailure="yes">
<classpath>
<pathelement path="${test.build}"/>
<pathelement path="${build}"/>
<path refid="project.classpath"/>
</classpath>
<formatter type="plain" />
<batchtest fork="no" todir="${test.log}">
<fileset dir="${test.src}">
<include name="**/*.java"/>
</fileset>
</batchtest>
</junit>
</target>
<target name="test-cvs" depends="build-test">
<mkdir dir="${test.log}"/>
<junit printsummary="yes" fork="yes" haltonfailure="yes">
<classpath>
<pathelement path="${test.build}"/>
<pathelement path="${build}"/>
<fileset dir="lib" includes="*.jar"/>
<fileset dir="/usr/local/ant/lib" includes="*.jar"/>
</classpath>
<formatter type="plain" />
<batchtest fork="no" todir="${test.log}">
<fileset dir="${test.src}">
<include name="**/*.java"/>
</fileset>
</batchtest>
</junit>
</target>
<target name="clean-test">
<delete dir="${test.build}"/>
<delete dir="${test.log}"/>
</target>
<!-- ********* version targets ************* -->
<target name="setversion" if="version">
<echo message="updating version in ${versionfile} ..."/>
<exec executable="perl">
<arg value="-i"/>
<arg value="-pe"/>
<arg value='s/(String\s*version\s*=\s*")[^"]*/$1${version}/' />
<arg value="${versionfile}"/>
</exec>
</target>
<target name="commit" depends="setversion,test-cvs" if="version">
<antcall target="cvsclean"/>
<echo message="---------------------------------------------------"/>
<echo message=' Commiting new Jode version: ${version} !!!'/>
<echo message="==================================================="/>
<!--
search the old version information and replace it with the new version
we will search the $(mainclass) for 'String VERSION = "..."' and
replace the contents of the String with the new version.
-->
<!-- commit the new $(VERSIONFILE) to the CVS
<echo message="commiting updated file to CVS..."/>
<cvs command='ci -m"new version ${version}" ${versionfile}'/>
-->
<!-- commit the new $(VERSIONFILE) to the CVS
<echo message="tagging files in CVS..."/>
<property
<cvs command="tag ${cvstag}"/>
-->
<echo message="...done!"/>
<echo message="---------------------------------------------------"/>
</target>
</project>

@ -1,28 +0,0 @@
# Do you have online access for generating javadoc?
# If not, where are your local files.
javadoc.offline=false
javadoc.packagelistLoc=
javadoc.href=http://java.sun.com/products/jdk/1.2/docs/api/
#javadoc.href=file:/usr/doc/inet/java/jdk1.2/docs/api
#javadoc.offline=true
#javadoc.packagelistLoc=/usr/doc/inet/java/jdk1.2/docs/api
# Is Perl installed on your system?
#
# perl is needed to reconfigure Jode for JDK-1.1. If you haven't
# installed it you can only configure for JDK-1.2 and you should
# comment out the next line.
#
# perl is also used for things that are relevant for the maintainer.
#
# Remove the next line if perl is not installed.
perl.present=true
# Is HTP installed on your system?
#
# htp is needed to generate html files from htp files.
# see http://htp.sourceforge.net/
#
# Remove the next line if either htp is not installed.
htp.present=true

@ -0,0 +1,139 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT()
AM_INIT_AUTOMAKE(jode, 1.0.90)
dnl Checks for programs.
dnl AC_PROG_CXX
dnl AC_PROG_AWK
dnl AC_PROG_CC
dnl AC_PROG_CPP
dnl AC_PROG_INSTALL
dnl AC_PROG_LN_S
AC_PROG_MAKE_SET
dnl AC_PROG_RANLIB
dnl AC_PATH_PROG(ZIP, zip)
AC_PATH_PROG(UNZIP, unzip)
dnl Checks for libraries.
dnl Checks for header files.
dnl Checks for typedefs, structures, and compiler characteristics.
dnl Checks for library functions.
dnl hack to quote Makefile lines
QUOTE=""
AC_SUBST(QUOTE)
AC_SUBST(SHELL)
AC_ARG_WITH(java,
[ --with-java specify path to a java-like program ],
[
if test ${withval} != "" || test ${withval} != "yes" || test ${withval} != "no"; then
# set javac to user input value
JODE_CHECK_JAVA(${withval})
else
JODE_CHECK_JAVA(/usr/lib/java)
fi
],
[
JODE_CHECK_JAVA(/usr/lib/java)
])
dnl jikes can also handle dependancies.
AC_ARG_WITH(jikes,
[ --with-jikes specify location of jikes ],
[
USER_SPECIFIED_JIKES=true
if test "${withval}" = "yes" || test "${withval}" = ""; then
AC_PATH_PROG(JIKES, jikes, "", $PATH)
else
echo "searching jikes in ${withval}:$PATH"
AC_PATH_PROG(JIKES, jikes, "", ${withval}:$PATH)
fi
if test -n "$JIKES"; then
JAVAC=$JIKES
fi
],
[
USER_SPECIFIED_JIKES=
AC_PATH_PROG(JIKES, jikes, "", $PATH)
])
AM_CONDITIONAL(HAVE_JIKES, test x"$JIKES" != x)
AC_ARG_WITH(javac,
[ --with-javac specify location of javac ],
[
if test x$USER_SPECIFIED_JIKES == xtrue; then
AC_MSG_ERROR(You must only give one option --with-javac or --with-jikes)
fi
if test ${withval} != "" || test ${withval} != "yes" || test ${withval} != "no"; then
AC_CHECK_FILES(${withval},
[ JAVAC=${withval} ],
[ AC_MSG_ERROR(${withval} does not exists) ])
fi
], [ true ])
JODE_CHECK_CLASS(java.lang.Object, $CLASSLIB,
[ true ],
[ AC_MSG_ERROR(Please specify location of java class library for jikes) ])
AC_MSG_CHECKING(for collection classes)
JODE_CHECK_CLASS(java.util.Set, $CLASSPATH:$CLASSLIB,
[ COLLECTIONS="java.util" ],
[ JODE_CHECK_CLASS(com.sun.java.util.collections.Set, $CLASSPATH:$CLASSLIB,
[ COLLECTIONS="com.sun.java.util.collections" ],
[ AC_MSG_RESULT(no)
AC_MSG_ERROR(You need the Java 1.2 collection classes in your classpath)
])
] )
AC_MSG_RESULT($COLLECTIONS)
AC_SUBST(COLLECTIONS)
AC_MSG_CHECKING(for gnu.getopt)
JODE_CHECK_CLASS(gnu.getopt.Getopt, $CLASSPATH:$CLASSLIB,
[ AC_MSG_RESULT(yes) ],
[ AC_MSG_RESULT(no)
AC_MSG_ERROR(You need gnu getopt for java.) ])
AC_MSG_CHECKING(for swing)
JODE_CHECK_CLASS(javax.swing.JFrame, $CLASSPATH:$CLASSLIB,
[ JAVAX_SWING="javax.swing" ],
[ JODE_CHECK_CLASS(com.sun.swing.JFrame, $CLASSPATH:$CLASSLIB,
[ JAVAX_SWING="com.sun.java.swing" ],
[ JAVAX_SWING="no" ]) ] )
AC_MSG_RESULT($JAVAX_SWING)
AC_SUBST(JAVAX_SWING)
if test x"$JAVAX_SWING" != x; then
SWINGUI="swingui"
else
AC_MSG_WARN(Swing is not in classpath ... skipping swingui)
SWINGUI=""
fi
AC_SUBST(SWINGUI)
AC_SUBST(CLASSPATH)
AC_SUBST(JAVAC)
AC_OUTPUT(Makefile
jode/Makefile
jode/bytecode/Makefile
jode/decompiler/Makefile
jode/expr/Makefile
jode/flow/Makefile
jode/jvm/Makefile
jode/obfuscator/Makefile
jode/swingui/Makefile
jode/type/Makefile
jode/util/Makefile
jode/GlobalOptions.java
jode/swingui/Main.java
jode/swingui/PackagesTreeModel.java
bin/Makefile
bin/jode
doc/Makefile
test/Makefile)

@ -1,58 +0,0 @@
#!/bin/sh
create_jar() {
jar -xvf $HOME/java/jars/getopt.jar
rm -rf META-INF
jar -cvf ../jode-1.0.92-$1.jar AUTHORS COPYING README INSTALL NEWS doc/*.{html,jos,perl,gif} `find jode -name \*.class` gnu
rm -rf gnu
}
create_first() {
# first 1.1 version.
tar -xvzf jode-1.0.92.tar.gz
cd jode-1.0.92
CLASSPATH=$HOME/java/jars/getopt.jar:/usr/local/1.1collections/lib/collections.jar:/usr/local/swing-1.1/swingall.jar \
./configure --with-java=/usr/lib/java --with-jikes=/home/jochen/bin
make
create_jar 1.1
cd ..
rm -rf jode-1.0.92
}
create_second() {
# now 1.2 version.
tar -xvzf jode-1.0.92.tar.gz
cd jode-1.0.92
find -name \*.java -o -name \*.java.in | xargs jcpp -DJDK12
CLASSPATH=$HOME/java/jars/getopt.jar \
./configure --with-java=/usr/local/jdk1.2 --with-jikes=/home/jochen/bin
make
create_jar 1.2
cd ..
rm -rf jode-1.0.92
}
create_applet() {
cat <<EOF >jode-applet.jos
# JODE Optimizer Script
strip = "unreach","source","lnt","lvt","inner"
load = new WildCard { value = "jode" },
new WildCard { value = "gnu" }
preserve = new WildCard { value = "jode.JodeApplet.<init>.()V" }
renamer = new StrongRenamer {
charsetStart = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
charsetPart = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$"
charsetPackage = "abcdefghijklmnopqrstuvwxyz"
charsetClass = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
}
analyzer = new ConstantAnalyzer
post = new LocalOptimizer, new RemovePopAnalyzer
EOF
CLASSPATH=jode-1.0.92-1.1.jar:$CLASSPATH java jode.obfuscator.Main \
--cp jode-1.0.92-1.1.jar --dest jode-applet.jar jode-applet.jos
}
#create_first
#create_second
create_applet

@ -1,3 +1,2 @@
Makefile
Makefile.in
*.html

@ -0,0 +1,5 @@
## Input file for automake to generate the Makefile.in used by configure
EXTRA_DIST = \
jode.html jode-applet.html jode-obfuscator.html jode-unix.html \
jode-useapplet.html jode-win.html

@ -1,25 +0,0 @@
<section title="The <i>JODE</i> Applet">
<p>Please be patience, loading the applet may take some time.</p>
<center>
<applet code="jode/Applet.class" archive="jode-applet.jar" width=540 height=400>
<param name=pagecolor value="ffffff">
<param name=classpath value="http://jode.sourceforge.net/plasma.jar">
<param name=class value="PlasmaApplet">
<p>Sorry you need a java enabled browser to test a java applet ;-)</p>
<p>Don't read the rest, it only contains information about the applet.</p>
</applet>
</center><br>
<p> Press the start button to decompile <a
href="http://www.informatik.uni-oldenburg.de/~mw/plasma.html">Michael's
Plasma applet</a> (and give the decompiler some time to download the
jar file). </p>
<p>You may change the classpath to point to a zip or jar file of your
choice. Unfortunately, your browser will most likely forbid URL's that
aren't located on jode.sourceforge.net.
Save probably doesn't work, because it is forbidden by your browser.</p>
</section>

@ -1,69 +0,0 @@
<section title="Wish List">
<p>This section contains features that I think would be great to have,
but are also very hard to implement. </p>
<p>Currently this are all my own ideas. But if you send me an idea
for an interesting feature, I will add it to this list.</p>
<h2><i>Out</i>line inlined methods</h2>
<p>If java gets called with `<code>-O</code>' switch, it inlines methods,
that are private, final, or static and contain no loops. When
decompiling this it sometimes produces really ugly code. The right
way to solve this would be to <i>out</i>line the code again. This is
possible but requires to find the inlined method. </p>
<p>The name `outline' was suggested by <a
href="http://www.informatik.uni-oldenburg.de/~mw">Michael</a>.
</p>
<h2>Better names of local variables</h2>
<p>The local variable naming is very stupid. Even with pretty it just
names the variable after the type with a unifying number appended. A
method containing very much objects of the same type looks very
ugly. </p>
<p>My plan is looking at the assignments. If we have locals in
assignments</p>
<pre>
int l_1 = array.length
String l_2 = object.getName()
</pre>
<p>we could name them "length" and "name". If we
have assignments:</p>
<pre>
MenuItem local_1 = new MenuItem("Open");
MenuItem local_2 = new MenuItem("Save");
</pre>
<p>good names would be <code>miOpen</code> and <code>miSave</code>. </p>
<p>It is currently possible to assign a <i>(hint name,type)</i> pair
to a local. If the type matches, the local will be named after
<i>hint name</i>. This could be extended by giving them several
weighted hints and constructing the name in an intelligent way. </p>
<h2>Better deobfuscation features</h2>
<p>First there should be a good Renamer: Methods that simply
return a field value should be renamed to get<i>FieldName</i>.
Fields should be named after their type, maybe also by assignments
(see section about local variable names).</p>
<p>The deobfuscator should detect inner and anonymous variables,
synthetic methods and so on, and rename them accordingly.</p>
<h2>Handling of Class.forName in obfuscator</h2>
<p>The obfuscator should detect Class.forName constructs (and
similarly for methods and fields) and if their parameters are constant
it should change the parameter according to the rename function. </p>
<h2>Merging javadoc comments</h2>
<p>It would be nice if the decompiler could merge the javadoc comments
into the class file. More and more people use javadoc to comment the
public api of their java classes. It shouldn't be too difficult to
copy them back into the java code. </p>
<p>This doesn't need to be built into the decompiler. A script that takes
the javadoc pages and the decompiled code can easily merge them.</p>
</section>

@ -1,711 +0,0 @@
use strict;
my (@tstack, @vstack);
my $incindent = 4;
my $instr_addr;
my (%instr, %next_instr, %prev_instr);
@tstack = ();
@vstack = ();
sub print_stack {
my ($type, $value);
while (@tstack and @vstack) {
$type = shift @tstack;
$value = shift @vstack;
print STDERR "($type) $value, ";
}
if (@tstack) {
print STDERR "TSTACK to big : @tstack ";
} elsif (@vstack) {
print STDERR "VSTACK to big : @vstack ";
}
@tstack = ();
@vstack = ();
}
sub print_code {
my ($indent, $code, $addr) = @_;
#print " "x$indent, $code, (defined addr)?"/* $addr */":"", "\n";
print " "x$indent, $code, "\n";
}
sub dump_program {
my $addr;
foreach $addr (sort { $a <=> $b } keys %instr) {
print_code (0, "$addr $instr{$addr}");
}
return 1
}
sub convert_value($$$) {
my ($value, $oldtype, $newtype) = @_;
return "$value" if ($oldtype eq $newtype);
return "$value" if ($oldtype =~ /\*/ or $newtype =~ /\*/);
return "$value" if ($oldtype eq "boolean" && $newtype eq "int");
if ($oldtype eq "int" && $newtype eq "boolean") {
$value =~ s/1/true/g;
$value =~ s/0/false/g;
$value =~ s/\&/\&\&/g;
$value =~ s/\|/\|\|/g;
return $value;
}
return $value; # "/*warn: conv: $oldtype => $newtype*/ $value";
}
sub get_type ($) {
my $type;
$_ = $_[0];
SWITCH: {
/^b$/ && ($type = "byte",last);
/^c$/ && ($type = "char",last);
/^s$/ && ($type = "short",last);
/^i$/ && ($type = "int",last);
/^l$/ && ($type = "long",last);
/^f$/ && ($type = "float",last);
/^d$/ && ($type = "double",last);
/^a$/ && ($type = "*",last);
die "internal error in get_type";
}
return $type;
}
sub pop_value_type ($) {
if (not @tstack || not @vstack) {
die "Stack is empty??";
}
my $result = "";
my $want_type = $_[0];
my $act_type = pop @tstack;
my $value = pop @vstack;
warn "want_type not defined"
if (not defined $want_type);
warn "act_type not defined"
if (not defined $act_type);
$result = convert_value($value, $act_type, $want_type);
return ($result, $act_type);
}
sub pop_value($) {
@_ = pop_value_type($_[0]);
return $_[0];
}
sub parse_type($) {
$_[0] =~ /^\#\d+\s+ <Class
\s+(\S+) # type
>\s*$/x or die "Wrong field parameter `$_[0]'";
return $1;
}
sub parse_field($) {
$_[0] =~ /^\#\d+\s+ <Field
\s+(\S+) # type
\s+([^\[>]+) # name
((?:\[\])*) # [][]... belongs to type
>\s*$/x or die "Wrong field parameter `$_[0]'";
return $1.$3, $2;
}
sub parse_special($) {
$_[0] =~ /\#\d+\s+<Method
\s+([^\(\s]+) # method
\s*\(([^\)]*)\) # params
>\s*$/x or die "Wrong method parameter `$_[0]'";
my ($method, $params) = ($1,$2);
my @params = split /,\s*/, $params;
return $method, @params;
}
sub parse_method($) {
$_[0] =~ /\#\d+\s+<Method
\s+(\S+) # type
\s+([^\(\s]+) # method
\s*\(([^\)]*)\) # params
>\s*$/x or die "Wrong method parameter `$_[0]'";
my ($type, $method, $params) = ($1, $2,$3);
my @params = split /,\s*/, $params;
return $type, $method, @params;
}
sub classify($$) {
my $class = $_[0] . ".";
$class = "" if $class eq "this.";
return $class.$_[1];
}
sub new_instr($) {
if (defined ($instr{$instr_addr})) {
$instr{$instr_addr} .= "\n/*warn: multiple*/\n".$_[0];
} else {
$instr{$instr_addr} = $_[0];
}
# print STDERR "$instr_addr: $instr{$instr_addr}\n";
}
sub new_assign($$) {
my ($var, $value) = @_;
if (@vstack) {
if (("$value" eq "($var + 1)") &&
($vstack[-1] eq "$var")) {
$vstack[-1] = "$var++";
} else {
warn("`$var = $value' in expression, while vstack");
}
} else {
new_instr("$var = $value;");
}
}
sub combine_if_block {
my ($addr, $end) = @_;
$instr{$addr} =~ /if (\(.*\)) goto (\d+);/ or return;
my ($cond, $dest) = ($1, $2);
COMBINE:
while (1) {
my $if;
# First combine ifs with the same dest addr, that is ors.
my @conds = ($cond);
for ($if = $next_instr{$addr}; $if < $end; $if = $next_instr{$addr}) {
$instr{$if} =~ /if (\(.*\)) goto ($dest);/ or last;
push @conds, $1;
#remove unnecessary ifs (hope there are no goto's)
$next_instr{$addr} = $next_instr{$if};
$prev_instr{$next_instr{$if}}= $addr;
delete $instr{$if};
delete $prev_instr{$if};
delete $next_instr{$if};
}
if (@conds > 1) {
# combine conditions with or and reset the list
$cond = join " || ", @conds;
$cond = "($cond)";
}
last COMBINE if ($if >= $end || $instr{$if} !~ /^if/);
# Now try if we can combine all further ifs until the destination (that is and)
combine_if_block($if, $dest)
unless ($next_instr{$if} == $dest);
last COMBINE if ($next_instr{$if} != $dest);
# This is an and
$instr{$if} =~ /if (\(.*\)) goto (\d+);/;
$cond = "(!$cond && $1)";
$dest = $2;
$next_instr{$addr} = $next_instr{$if};
$prev_instr{$next_instr{$if}}= $addr;
delete $instr{$if};
delete $prev_instr{$if};
delete $next_instr{$if};
}
# Okay, we are stuck here, build the combined if.
$instr{$addr} = "if $cond goto $dest;";
}
sub simplify_instructions {
my ($addr, $end) = @_;
ADDR:
for (; $addr < $end; $addr = $next_instr{$addr}) {
combine_if_block($addr, $end)
if $instr{$addr} =~ /^if /;
while ( $instr{$addr} =~
/^(.*)new (java\.lang\.)?StringBuffer\((\).append\(.*)+\).toString\(\)(.*)$/ ) {
my ($first, $middle, $last) = ($1,$3,$4);
$middle =~ s/\).append\(/\+/g;
$middle =~ s/^\+//;
$instr{$addr} = $first.$middle.$last;
}
while ( $instr{$addr} =~ s/([A-Za-z_\$][A-Za-z_\$0-9]*) = \(\1 \+ 1\)/$1++/) {
}
}
}
# The parameters:
# start first instruction to decode
# end last instruction to decode + 1
# next instruction where control flows after this block
# (usually end but may be bigger)
# break instruction where a break would bring us to
# indent The indentation of this block
sub print_stmtlist ($$$$$) {
my ($start, $end, $next, $break, $indent) = @_;
my $addr;
$addr = $start;
ADDR:
while ($addr < $end) {
(dump_program && die "Addresses out of range: $addr") if (not defined $next_instr{$addr});
$_ = $instr{$addr};
/^goto (\d+);$/ && do {
my $dest = $1;
if ($dest == $break) {
print_code($indent, "break $dest;", $addr);
$addr = $next_instr{$addr};
next ADDR;
}
my $begin = $next_instr{$addr};
if ($instr{$dest} =~ /^if\s\((.*)\)\sgoto\s$begin/) {
# This is a while-loop
print_code($indent, "while ($1) {", $addr);
print_stmtlist($begin, $dest, $dest, $dest, $indent+$incindent);
print_code($indent, "}");
$addr = $next_instr{$dest};
next ADDR;
}
};
/^if \((.*)\) goto (\d+);/ && do {
my $cond = $1;
my $next_after_if = $2;
if ($next_after_if > $addr &&
($next_after_if <= $end || $next_after_if == $next)) {
# This seems to be an if.
print_code($indent, "if (!($cond)) {", $addr);
# endthen is the last instruction in then block + 1
my $endthen = ($next_after_if > $end) ? $end : $next_after_if;
my $prev = $prev_instr{$endthen};
if ($instr{$prev} =~ /^goto\s(.*);/ &&
$1 > $endthen && ($1 <= $end || $1 == $next)) {
$next_after_if = $1;
my $endelse = $1;
if ($endelse > $end) {
$endelse = $end;
}
# there is an else part
print_stmtlist ($next_instr{$addr}, $prev,
$next_after_if, $break, $indent+$incindent);
print_code($indent, "} else {");
print_stmtlist ($endthen, $endelse,
$next_after_if, $break, $indent+$incindent);
$addr = $endelse;
} else {
# no else-part
print_stmtlist ($next_instr{$addr}, $endthen,
$next_after_if, $break, $indent+$incindent);
$addr = $endthen;
}
print_code($indent, "}");
next ADDR;
}
if ($next_after_if == $break) {
# This is an if () break;
print_code($indent, "if ($cond) break;", $addr);
$addr = $next_instr{$addr};
next ADDR;
}
};
/^case ((.|\n)*)$/ && do {
my $default;
my $cond = "NONE";
my @lines = split "\n", $1;
$_ = shift @lines;
/^\((.*)\)$/ and $cond = $1;
(shift @lines) =~ /^default: goto (\d+);/ and $default = $1;
my $next_after_switch = $default;
if ($instr{$prev_instr{$default}} =~ /^goto\s(\d+);/ and
$1 > $default) {
$next_after_switch = $1;
}
print_code ($indent, "switch ($cond) {", $addr);
my %cases = ($default => "default");
foreach (@lines) {
(/^(\d+): goto (\d+);$/ and $cases{$2} = "case $1")
or warn ("ILLEGAL case : `$_'");
my $casepos = $1;
if ($casepos > $next_after_switch) {
if ($instr{$prev_instr{$1}} =~ /^goto\s(\d+);/ and
$1 > $casepos) {
$next_after_switch = $1;
} else {
$next_after_switch = $casepos;
}
}
}
$next_after_switch = $end
if ($next_after_switch > $end && $next_after_switch != $next);
my $endswitch = ($next_after_switch > $end) ? $end : $next_after_switch;
#print STDERR "Addr: $addr, labels: `",
# (join ":", keys %cases ), "', default: $default, end: $next_after_switch\n";
$addr = $next_instr{$addr};
foreach $_ (sort { $a <=> $b } keys %cases) {
my $next_case = $_;
if ($instr{$prev_instr{$next_case}} eq
"goto $next_after_switch;") {
print_stmtlist($addr, $prev_instr{$next_case},
$next_after_switch, $next_after_switch,
$indent+$incindent);
print_code($indent+$incindent, "break;");
} else {
print_stmtlist($addr, $next_case,
$next_case, $next_after_switch,
$indent+$incindent);
}
print_code($indent, $cases{$next_case}.":");
$addr = $next_case;
}
print_stmtlist($addr, $endswitch,
$endswitch, $next_after_switch,
$indent+$incindent);
print_code($indent, "}");
$addr = $endswitch;
next ADDR;
};
print_code($indent, $_, $addr);
$addr = $next_instr{$addr};
}
}
my %locals = ();
my $addr;
LINE: while (<>) {
chomp;
(/^\s*(\d+)\s+(.*)$/ and $addr = $1, $_ = $2) or do {
warn "Line `$_' ist not formatted correctly\n";
next LINE;
};
if (not @vstack) {
if (defined ($instr_addr)) {
new_instr("/*warn: missing instruction!*/")
if (not defined $instr{$instr_addr});
$next_instr{$instr_addr} = $addr;
$prev_instr{$addr} = $instr_addr;
} else {
$prev_instr{$addr} = -1;
}
$instr_addr = $addr;
}
INSTR:
{
/^([ilfda])load[\s_]+(\d+)\s*$/ && do {
push @tstack, get_type($1);
my $local;
if ($2 == 0) {
$local = "this";
} else {
$local = "local_$2";
}
push @vstack, $local;
last INSTR;
};
/^([bcsilfda])aload\s*$/ && do {
my $warn = "";
my $index = pop_value("int");
my ($array, $atype) = pop_value_type(get_type($1)."[]");
my $type = $atype;
($atype =~ /(.*)\[\]/ and $type = $1) or
$warn = "/*warn: `$atype' not an array*/ ";
push @tstack, $type;
push @vstack, "$warn$array"."[$index]";
last INSTR;
};
(/^[bs](i)push\s+(-?\d+)\s*$/ ||
/^([ilfda])const[\s_]+([m\-]?[\d.Ee\+\-]+|null)\s*$/) && do {
push @tstack, get_type($1);
push @vstack, ($2 eq "m1") ? -1 : $2;
last INSTR;
};
/ldc[12]?_?w?\s+\#\d+\s+\<(\S+)\s+([^\>]+)\>/ && do {
push @tstack, $1;
push @vstack, $2;
last INSTR;
};
/^([ilfda])store[\s_]+(\d+)\s*$/ && do {
my $local;
my ($value, $type) = pop_value_type(get_type($1));
if ($2 == 0) {
$local = "this";
} else {
$local = "local_$2";
if (not defined $locals{$2}) {
$locals{$2} = $type;
$local = "$type $local";
} else {
$local = convert_value($local, $type, $locals{$2});
}
}
new_assign($local, $value);
last INSTR;
};
/^([bcsilfda])astore\s*$/ && do {
my ($value, $type) = pop_value_type(get_type($1));
my $index = pop_value("int");
my ($array, $atype) = pop_value_type(get_type($1)."[]");
($atype =~ /(.*)\[\]/ and $atype = $1) or
$atype = "`$atype' not an array*/\n\t";
new_assign("$array"."[$index]",
convert_value("$value", $type, $atype));
last INSTR;
};
/^new\s+(.*)\s*/ && do {
my ($type) = parse_type($1);
push @tstack, $type;
push @vstack, "new $type";
last INSTR;
};
/^newarray\s+(\S+)\s*$/ && do {
my $arrtype = $1;
my $value = pop_value("int");
push @tstack, $arrtype."[]";
push @vstack, "new ".$arrtype."[$value]";
last INSTR;
};
/^getfield\s+(.*)$/ && do {
my ($type, $field) = parse_field($1);
my $class = pop_value("*") . ".";
$class = "" if $class eq "this.";
push @tstack, $type;
push @vstack, "$class$field";
last INSTR;
};
/^getstatic\s+(.*)$/ && do {
my ($type, $field) = parse_field($1);
push @tstack, $type;
my $class="FIXME.";
push @vstack, "$class$field";
last INSTR;
};
/^putfield\s+(.*)$/ && do {
my ($dtype, $field) = parse_field($1);
my $value = pop_value($dtype);
$field = classify(pop_value("*"), $field);
new_assign($field, $value);
last INSTR;
};
/^goto\s+(\d+)\s*$/ && do {
new_instr("goto $1;");
last INSTR;
};
/^tableswitch\s+(\d+)\s+to\s+(\d+): default=(\d+)\s*$/ && do {
my $from = $1;
my $to = $2;
my $default = $3;
my $num;
my $casestmt = "case (" . pop_value("int") . ")\n";
$casestmt .= "default: goto $default;\n";
for $num ($from .. $to) {
$_ = <>;
if ( $_ =~ /\s+$num:\s*(\d+)/ ) {
$casestmt .= "$num: goto $1;\n";
} else {
warn "unknown case: `$_' at $.";
}
}
new_instr($casestmt);
last INSTR;
};
/^lookupswitch\s+(\d+):\s+default=(\d+)\s*$/ && do {
my $anz = $1;
my $default = $2;
my $num;
my $casestmt = "case (" . pop_value("int") . ")\n";
$casestmt .= "default: goto $default;\n";
for $num (1 .. $anz) {
$_ = <>;
if ( $_ =~ /\s+(\d+):\s*(\d+)/ ) {
$casestmt .= "$1: goto $2;\n";
} else {
$casestmt .= "error in case";
}
}
new_instr($casestmt);
last INSTR;
};
/^invokespecial\s+(.*)$/ && do {
my ($method, @paramtypes) = parse_special ($1);
my @params=();
# Constructoraufruf! Wenn alles glatt laeuft...
while (@paramtypes) {
my $ptype = pop @paramtypes;
my $value = pop_value($ptype);
unshift @params, $value;
}
my ($new_class, $class_type) = pop_value_type ("*");
$method = $new_class;
my $call = "$method(" . join (", ", @params) . ")";
if ($vstack[-1] eq $new_class) {
$vstack[-1] = "$call";
} else {
new_instr("$call;");
}
last INSTR;
};
/^invoke(virtual|static)\s+(.*)$/ && do {
my ($type, $method, @paramtypes) = parse_method ($2);
my @params=();
while (@paramtypes) {
my $ptype = pop @paramtypes;
my $value = pop_value($ptype);
unshift @params, $value;
}
my ($class, $class_type) = ($1 eq "virtual")? pop_value_type ("*") : "FIXME";
$method = classify($class, $method);
my $call = "$method(" . join (", ", @params) . ")";
if ($type eq "void") {
new_instr("$call;");
} else {
push @tstack, $type;
push @vstack, $call;
}
last INSTR;
};
/^return\s*$/ && do {
new_instr("return;");
last INSTR;
};
/^pop\s*$/ && do {
unless (@vstack) {
print STDERR "pop: Stack is empty at $addr";
}
new_instr(pop(@vstack).";");
pop @tstack;
last INSTR;
};
/^dup\s*$/ && do {
push @tstack, $tstack[-1];
push @vstack, $vstack[-1];
last INSTR;
};
/^dup2\s*$/ && do {
push @tstack, $tstack[-2];
push @vstack, $vstack[-2];
push @tstack, $tstack[-2];
push @vstack, $vstack[-2];
last INSTR;
};
/^dup_x([12])\s*$/ && do {
splice @tstack, -1-$1, 0, $tstack[-1];
splice @vstack, -1-$1, 0, $vstack[-1];
last INSTR;
};
/^([ilfd])neg\s*$/ && do {
my $type = get_type($1);
my $op1 = pop_value($type);
push @tstack, $type;
push @vstack, "-$op1";
last INSTR;
};
/^([ilfd])(add|sub|mul|div|rem|and|or|xor|shl|shr)\s*$/ && do {
my $type = get_type($1);
my $op2 = pop_value($type);
my $op1 = pop_value($type);
my $op;
for ($2) {
/add/ && ($op="+", last);
/sub/ && ($op="-", last);
/mul/ && ($op="*", last);
/div/ && ($op="/", last);
/rem/ && ($op="%", last);
/and/ && ($op="&", last);
/or/ && ($op="|", last);
/xor/ && ($op="^", last);
/shl/ && ($op="<<", last);
/shr/ && ($op=">>", last);
}
push @tstack, $type;
push @vstack, "($op1 $op $op2)";
last INSTR;
};
/^iinc\s+(\d+)\s+(-?\d+)\s*$/ && do {
my $value = $2;
my $local;
if ($1 == 0) {
$local = "this";
} else {
$local = "local_$1";
}
new_instr(convert_value("$local", "int", $locals{$1}).
(($2 == 1)? "++;" : " += $2;"));
last INSTR;
};
/^([bcifld])2([bcifld])\s*$/ && do {
my $value = pop_value(get_type($1));
my $type = get_type($2);
push @tstack, $type;
push @vstack, "($type) $value";
last INSTR;
};
/^([lfd])cmp([lg]?)\s*$/ && do {
my $type = get_type($1);
my $op2 = pop_value($type);
my $op1 = pop_value($type);
push @tstack, "int";
push @vstack, "($op1 <=>$2 $op2)";
last INSTR;
};
/^if(eq|lt|le|ne|gt|ge)\s+(\d+)\s*$/ && do {
my $op;
my $dest = $2;
for ($1) {
/eq/ && ($op="==", last);
/lt/ && ($op="<", last);
/le/ && ($op="<=", last);
/ne/ && ($op="!=", last);
/gt/ && ($op=">", last);
/ge/ && ($op=">=", last);
}
my $op1 = pop_value("int");
new_instr("if ($op1 $op 0) goto $dest;");
last INSTR;
};
/^if_icmp(eq|lt|le|ne|gt|ge)\s+(\d+)\s*$/ && do {
my $op;
my $dest = $2;
for ($1) {
/eq/ && ($op="==", last);
/lt/ && ($op="<", last);
/le/ && ($op="<=", last);
/ne/ && ($op="!=", last);
/gt/ && ($op=">", last);
/ge/ && ($op=">=", last);
}
my $op2 = pop_value("int");
my $op1 = pop_value("int");
new_instr("if ($op1 $op $op2) goto $dest;");
last INSTR;
};
/^if(null|nonnull)\s+(\d+)\s*$/ && do {
my $dest = $2;
my $op;
for ($1) {
/notnull/ && ($op="!=", last);
/null/ && ($op="==", last);
}
my $op1 = pop_value("*");
new_instr("if ($op1 $op null) goto $dest;");
last INSTR;
};
do {
print STDERR "Stack: ";
&print_stack;
print STDERR "\nUnknown Instruction: `$_'\n\t";
};
}
}
$addr++;
$next_instr{$instr_addr} = $addr;
simplify_instructions (0, $addr);
print_stmtlist(0, $addr, $addr, $addr, 2*$incindent);

@ -1,39 +0,0 @@
<section title="Download">
<p>Jode is available in the <sflink
href="project/showfiles.php">download area</a> in source or binary
form. For compiling the source code, you need several other packages,
check the <a href="links.html">links page</a>. You need a unix like
environment for compilation.</p>
<p>The simplest way to get it, especially for non unix users, is in
precompiled form, though. There are two jar archives in the download
area:</P>
<ul> <li>jode-1.1-JDK1.1.jar is for JDK&nbsp;1.1. If you want to use
the swing interface, you have to download swing separately, all other
packages are already included in the archive. </li>
<li>jode-1.1.jar is for JDK&nbsp;1.2 or better. It should run
without any other package.</li> </ul>
</section>
<section title="Subversion Repository">
<p>You can get the latest sources from the <a
href="http://sourceforge.net/svn/?group_id=3790">SVN repository</a>.
Follow the instruction on that page; use
<code>/svnroot/jode/trunk/jode</code> as last part of the URL. If you
want to checkout a specific version you can checkout the URL
<code>.../svnroot/jode/tags/xxx/jode</code>:</p>
<ul>
<li><code>../jode/tags/jode_1_0_93/jode</code>: checks out the version 1.0.93</li>
<li><code>../jode/branches/branch_1_1/jode</code>: checks out the latest version in the
1.1 series.</li> </ul>
<p>To build the sources from latest SVN change to the main directory and invoke ant.</p>
<p>To build the 1.1 versions of jode change to the main directory and run
<pre>aclocal && automake -a && autoconf</pre>
<p>Afterwards follow the instruction in the INSTALL file. </p>
</section>

@ -1,90 +0,0 @@
<section title="FAQ - Frequently Asked Questions">
This is a list of some questions that pop up from time to time.
</section>
<section title="Decompiler issues">
<h3>Does Jode support Java 5?</h3>
<p>It does not support generics/vararg method or the new for loop at
the moment. It produces readable code and I think it may even compile
again. But it is not compatible as the generics and varargs
information is not included.</p>
<h3>Jode crashes with ExceptionHandler order failed</h3>
<p>Try jode-1.1.2pre1 or the latest CVS version. If it still does not
work rewrite <code>jode.flow.TransformExceptionHandlers</code> and
send me the fix :) </p>
<p>Since Java 1.4 the format for finally and synchronized blocks
changed again. It was always a very difficult task to reconstruct
<code>finally</code> blocks correctly and the code is huge and very
hard to maintain. With Java 5 it gets even worse.</p>
<h3>The decompiler crashes with a VerifyException, what can I do?</h3>
<p>The class isn't verifiable, probably because there is not enough
information about used classes. See the question about the
classpath.</p>
<p>This could also be caused by malicious bytecode, or because there
is a bug in Jode's verifier, or because Sun decided to change the
definition of correct bytecode, again.</p>
<h3>What should be included in the classpath?</h3>
<p>Jode needs to know the full class hierarchie to guess the types.
This includes not only the classes in the program, but also the
libraries used by the java program, even the Java runtime library.
You should set the classpath to include all these classes.</p>
<p>If you don't specify the classpath on the command line, Jode uses
the same as your Java Virtual Machine.</p>
<p>As last resort, if Jode can't find a class in the classpath it uses
reflection to ask the Virtual Machine. This works quite well, but
loading classes can have side effects, e.g. when AWT classes are
loaded, an AWT thread is created, even though Jode doesn't need
it.</p>
<h3>Why doesn't Jode decompile my inner class
<code>MyClass$Inner.class</code>?</h3>
<p>You should decompile the outermost class (<code>MyClass</code> in
this case). The produced code contains the inner class. </p>
</section>
<section title="Obfuscator issues">
<h3>What should be included in the classpath?</h3>
<p>The program, all libraries, the Java runtime library. Don't omit a
library even when you don't want to obfuscate it.</p>
<h3>What should I preserve</h3>
<p>The most common mistake is to preserve a class. In most cases this
is not what you want. This only makes sure the class won't be
renamed, it doesn't prevent it from being stripped. Instead you
should preserve methods and constructors. The constructor is just a
method with the special name <tt>&lt;init&gt;</tt>. </p>
<p> Another common mistake is to omit the type
signature, e.g. to preserve <tt>Class.main</tt> instead of
<tt>Class.main.([Ljava/lang/String;)V</tt>. That doesn't work. If
you don't want to care about the format of the type signature use a
wildcard as in <tt>Class.main.*</tt>. </p>
<h3>What is a type signature</h3>
<p>The type signature is a machine readable representation of a java
type that is used all over in java bytecode. The JDK ships a command
named <tt>javap</tt>. With <tt>java -s</tt> you can lists the fields
and methods of a class with their type signatures.</p>
<p> If you are interested in the format of type signatures read the
Java Virtual Machine Specification, Chapter 4.3 Descriptors</p>
</section>

@ -1,106 +0,0 @@
/* XPM */
static char * favicon_xpm[] = {
"16 16 87 1",
" c None",
". c #C2C2C2",
"+ c #A1A1A1",
"@ c #BBBBBB",
"# c #D9D9D9",
"$ c #BABABA",
"% c #C1C1C1",
"& c #ECECEC",
"* c #A7A7A7",
"= c #636363",
"- c #989898",
"; c #C3C3C3",
"> c #C5C5C5",
", c #A6A6A6",
"' c #747474",
") c #646464",
"! c #6D6D6D",
"~ c #8C8C8C",
"{ c #ABABAB",
"] c #A5A5A5",
"^ c #787878",
"/ c #A8A8A8",
"( c #606060",
"_ c #FFFFFF",
": c #626262",
"< c #7A7A7A",
"[ c #FEFEFE",
"} c #949494",
"| c #535353",
"1 c #919191",
"2 c #F0F0F0",
"3 c #5B5B5B",
"4 c #B3B3B3",
"5 c #5A5A5A",
"6 c #3E3E3E",
"7 c #4C4C4C",
"8 c #666666",
"9 c #616161",
"0 c #939393",
"a c #F8F8F8",
"b c #1C1C1C",
"c c #999999",
"d c #DFDFDF",
"e c #0D0D0D",
"f c #B1B1B1",
"g c #343434",
"h c #5D5D5D",
"i c #676767",
"j c #6F6F6F",
"k c #9E9E9E",
"l c #4F4F4F",
"m c #F7F7F7",
"n c #1B1B1B",
"o c #E7E7E7",
"p c #1D1D1D",
"q c #7C7C7C",
"r c #9B9B9B",
"s c #525252",
"t c #EFEFEF",
"u c #9C9C9C",
"v c #434343",
"w c #414141",
"x c #3D3D3D",
"y c #3F3F3F",
"z c #BFBFBF",
"A c #3A3A3A",
"B c #686868",
"C c #6B6B6B",
"D c #C4C4C4",
"E c #F4F4F4",
"F c #FAFAFA",
"G c #D7D7D7",
"H c #AFAFAF",
"I c #828282",
"J c #737373",
"K c #818181",
"L c #DEDEDE",
"M c #E9E9E9",
"N c #696969",
"O c #9F9F9F",
"P c #A2A2A2",
"Q c #717171",
"R c #B4B4B4",
"S c #E8E8E8",
"T c #898989",
"U c #767676",
"V c #DBDBDB",
" ",
" ",
" ",
" ",
" .++@ #$%& ",
"*=-;>,')!~{]^)/ ",
"(_:<[}|123:42567",
"8_,90=abc|defg*h",
"i_jklfmnj1opq(r=",
"9sgtugvuwxyzwAB:",
"}CDEFGHIJK{L[MNO",
" #PQCKRd S@TiUV ",
" ",
" ",
" ",
" "};

@ -1,11 +0,0 @@
<section title="Feedback">
<p>You can report bugs to the <?php sflink("bugs/")?>bug forum</a>. </p>
<p>You can contact me by email via <a
href="http://sourceforge.net/sendmessage.php?touser=18252">hoenicke at
users.sourceforge.net</a>. Please mention <i>jode</i> in the
subject.</p>
<p>There is a mailing list. Check <a href="http://lists.sourceforge.net/mailman/listinfo/jode-users">this page</a> for subscription informations.</p>
</section>

@ -1,13 +0,0 @@
<TABLE class=footer width="100%" border="0" cellspacing="0" cellpadding="2">
<TR>
<TD align="center"><SPAN class=footer>
All trademarks and copyrights on this page are properties of their respective owners. <br>
Last updated on 29-May-2002,
Copyright &copy; 1998-2002 by Jochen Hoenicke.
Canonic URL is <a class=boldlink href="http://jode.sourceforge.net/">http://jode.sourceforge.net/</a></SPAN>
</TD>
</TR>
</TABLE>
</BODY>
</HTML>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

@ -1,9 +0,0 @@
21 iconst_4
22 iand
23 ifne 30
26 iconst_0
27 goto 31
30 iconst_1
31 ireturn

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

@ -1,9 +0,0 @@
while (i>0) {
if (a[i] > max)
max = a[i];
if (a[i] == 0)
break;
i++;
}

@ -1,42 +0,0 @@
#FIG 3.2
Landscape
Center
Metric
A4
100.00
Single
-2
1200 2
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
1800 4725 2700 4725 2700 5400 1800 5400 1800 4725
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
2475 4275 3375 4275 3375 3600 2475 3600 2475 4275
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
2475 2475 3375 2475 3375 3150 2475 3150 2475 2475
2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 1
2475 3825
2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
2475 5850 3375 5850 3375 6525 2475 6525 2475 5850
2 1 0 1 0 7 100 0 -1 0.000 0 0 7 1 0 3
1 1 2.00 60.00 120.00
3600 5400 2925 5625 2925 5850
2 1 0 1 0 7 100 0 -1 0.000 0 0 7 1 0 3
1 1 2.00 60.00 120.00
2925 4275 2250 4500 2250 4725
2 2 0 1 0 7 100 0 -1 0.000 0 0 7 0 0 5
3150 4725 4050 4725 4050 5400 3150 5400 3150 4725
2 1 0 1 0 7 100 0 -1 0.000 0 0 7 1 0 2
1 1 2.00 60.00 120.00
2925 3150 2925 3600
2 1 0 1 0 7 100 0 -1 0.000 0 0 7 1 0 5
1 1 2.00 60.00 120.00
2250 5400 2250 5625 1350 5625 1350 3825 2475 3825
2 1 0 1 0 7 100 0 -1 0.000 0 0 7 1 0 3
1 1 2.00 60.00 120.00
2925 4275 3600 4500 3600 4725
2 1 0 1 0 7 100 0 -1 0.000 0 0 7 1 0 5
1 1 2.00 60.00 120.00
3600 5400 3600 5625 4275 5625 4275 3825 3375 3825
2 1 0 1 0 0 100 0 20 0.000 0 0 7 0 0 8
10800 2250 9675 3375 9675 2700 8325 2700 8325 1800 9675 1800
9675 1125 10800 2250

@ -1,63 +0,0 @@
<?php
if (! $extension) {
$extension = "php";
}
$version="1.1";
function selflink($link) {
global $extension;
echo "<a href=\"./";
if ($link != "index") {
if (ereg("#", $link)) {
$link = ereg_replace("#", ".$extension#", $link);
} else {
$link .= ".$extension";
}
echo "$link";
}
echo "\">";
}
function sflink($link) {
echo "<a href=\"http://sourceforge.net/$link?group_id=3790\">";
}
?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Java Optimize and Decompile Environment (JODE)</title>
<meta name="date" content="2001-05-29">
<meta name="description" content="JODE - Java Optimize and Decompile Environment.">
<meta name="author" content="Jochen Hoenicke">
<meta name="keywords" content="jode, java, decompiler, obfuscator, deobfuscator, reverse engineering, free, GPL">
<style type="text/css">
<!--
body { color:#000000; background-color: #FFFFFF; }
.nav { font-family: Helvetica, Arial, sans-serif; font-weight: bold;
color:#000000; background-color: #EEEEF8; }
.footer { color:#FFFFFF; background-color: #737B9C; }
.boldlink { font-weight:bold; text-decoration: none; color:#FFFFFF; }
//-->
</style>
</head>
<body text="#000000" bgcolor="#FFFFFF">
<table cellpadding=4 cellspacing=1 width="100%"
><tr
><td align="left"
><img src="jode-logo.gif" alt="JODE" width=286 height=110
></td
><td align="right"
>Powered by <a href="http://sourceforge.net"><img
src="http://sourceforge.net/sflogo.php?group_id=3790&amp;type=1"
border=0 width=88 height=31 alt="SourceForge"></a><br
>Best viewed with <a
href="http://www.anybrowser.org/campaign/"><img
src="a-logo.gif" border=0 width=88 height=31 alt="Any
Browser"></a><br
></td
></tr
></table>
<?php require("menu.inc"); ?>

@ -1,20 +0,0 @@
<section title="History">
<p>Someday I found <code>guavad</code>, a disassembler for java byte
code (it does similar things like <code>javap&nbsp;-c</code>). I used
it on a class file, and found that it was possible to reconstruct the
original java code. First I did it by hand on some small routines,
but I soon realized that it was a rather stupid task. So I wrote a
small <a href="dasm_to_java.perl"><code>perl</code> script</a> that
did this process automatically. At the end of the next day I had my
first working decompiler.</p>
<p>Now while the <code>perl</code> script is working, it is not easy
to use. You have to decompile the code first with a disassembler, cut
out the code of a single method, and run the perl script on it. I
decided to get the bytecode directly out of the class files and do
this all automatically. I decided to write it in <code>java</code>
now, because it suited best.</p>
<p>Just for the records: the java code is now more than 50 times
bigger than the original perl script and is still growing.</p>
</section>

@ -1,52 +0,0 @@
<opt quiet>
<file template="jode.htt">
<set version="1.1">
<set sfgroup="3790">
<def name="sflink" option="href">
<a href="http://sourceforge.net/${href}?group_id=${sfgroup}">
</def>
<def name="entry" option="name type href">
<if type="sflink">
<sflink href="$href"><use name></a>
<else>
<if _htpfile_out="${href}.html">
<use name>
<elseif $href="index">
<a href="."><use name></a>
<else>
<a href="${href}.html"><use name></a>
</if>
</if>
</def>
<block name=menu>
<entry name="<B>Home</B>" href="index">
<entry type=sflink name="Project page" href="project/">
<entry name="Applet" href="applet">
<entry name="Download" href="download">
<entry name="FAQ" href="faq">
<entry name="Feedback" href="feedback">
<entry name="Documentation" href="usage">
<entry name="License" href="license">
<entry name="History" href="history">
<entry name="Links" href="links">
<entry name="Blue Sky" href="bluesky">
</block>
<blockdef name=section option="title">
<if not sect_ctr><set sect_ctr="0" global></if>
<inc sect_ctr global>
<set title${sect_ctr}="$title" global>
<block name=section${sect_ctr} global expand>
<use block noexpand>
</block>
</blockdef>
<block name=everything>
<set i=1>
<while section$i>
<h1><use title$i></h1>
<use section$i>
<inc i>
</while>
</block>

@ -1,74 +0,0 @@
<section title="Introduction">
<P><i>JODE</i> is a java package containing a decompiler and an
optimizer for java. This package is <a href="license.html">freely
available</a> under the GNU GPL. The bytecode package and the core
decompiler is now under GNU Lesser General Public License, so you can
integrate it in your project.</p>
<P>The decompiler reads in <tt>class</tt> files and produces something
similar to the original <tt>java</tt> file. Of course this can't be
perfect: There is no way to produce the comments or the names of local
variables (except when compiled with debuging) and there are often
more ways to write the same thing. However, <i>JODE</i> does its job quite
well, so you should give it a try and <a href="applet.html">start the
applet</a>.</P>
<P>The optimizer transforms <tt>class</tt> files in various ways with
can be controlled by a script file. It supports the following
operations:</p>
<ul>
<li>Renaming class, method, field and local names to shorter,
obfuscated, or unique names or according to a given translation
table</li>
<li>Removing debugging information</li>
<li>Removing dead code (classes, fields, methods) and constant
fields</li>
<li>Optimizing local variable allocation</li>
</ul>
</section>
<section title="News">
<ul>
<li><i>JODE</i> 1.1.1 is out. With support for javac v8 (jdk 1.3). </li>
<li>The license changed to LGPL for the bytecode interface and decompiler.</li>
</ul>
</section>
<section title="Known Bugs">
<p>The current version has problems try/catch/finally code produced
by java 1.4 compiler. You may try the latest CVS version or pre-release
instead.</p>
<p>Some jdk1.3 synthetic access functions aren't understood. The
produced source contains access$xxx functions, but it still compiles.</p>
<p>There may be other bugs, that cause Exceptions or invalid code.
If you have such a problems don't hesitate to issue a bug report.
Please include the <code>class</code> file if possible.</p>
</section>
<section title="Limits">
<p>If not all dependent classes can be found, the verifier (which is
run before decompilation starts) may exit with a type error. You
can decompile it with <tt>--verify=off</tt>, but take the warning
serious, that types may be incorrect. There's sometimes no way to
guess the right type, if you don't have access the full class
hierarchie.<br>
This is not a bug in the verifier: java will complain the same way,
if it is run with bytecode verification turned on. And if you don't
have the dependent classes, you can't compile the code again.</p>
<p>There may be situations, where the code doesn't understand complex
expressions. In this case many ugly temporary variables are used, but
the code should still be compileable. This does especially happen
when you compile with <tt>`-O'</tt> flag and javac has inlined some
methods. </p>
</section>

@ -0,0 +1,39 @@
<html>
<head>
<title>Jode Test Applet</title>
</head>
<body>
<a href="jode.html">Up</a>
<h1>Test Applet</h1>
<applet code="jode/JodeApplet.class" archive="jode-applet.jar" width=640 height=400>
<param name=classpath
value="http://www.informatik.uni-oldenburg.de/~delwi/jode/jode_cls.zip">
<param name=class value="jode.JodeApplet">
</applet><br><br>
Press the start button to decompile this applet. You may change the
class path and class name to point to a class file of your choice.
But note that most browsers doesn't allow loading files from a
different server.<br><br>
Save probably doesn't work, because it is forbidden by the browser.<br><br>
You may give multiple entries in the class path field separated by a
comma. The components may be local or remote zip or jar files or
directories. Note that browsers forbid accesses to different hosts or
local files that are not in a subdirectory of the applet
directory.<br><br>
BTW: If you just want to read the source, you may <a
href="http://www.informatik.uni-oldenburg.de/~delwi/jode">browse it
online</a> <code>:-)</code><br><br>
You can download this, look <a href="jode-useapplet.html">here</a> for
a description.
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

@ -0,0 +1,15 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.0//EN">
<html>
<head>
<title>Using the obfuscator</title>
</head>
<body>
<a href="jode.html">Up</a>
The obfuscator currently takes a lot of options (I plan to use an
extra file containing the options). You should therefore create a
script (or batch file under Windows) that invokes the obfuscator.<br>
</body>

@ -0,0 +1,97 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.0//EN">
<html>
<head>
<title>Using the decompiler under Unix</title>
</head>
<body>
<a href="jode.html">Up</a>
<h1>Step by Step</h1>
You need java version 1.1 or higher. In the following description I
assume you have the JDK 1.1, residing in <code>/usr/lib/java</code>.
For other installations you have to adopt the paths. Also I use the
bourne shell syntax.
<ol>
<li> Set the classpath. It should include the jode_cls.zip as well as
the directory where the class files you want to decompile resides.
You can also specify a zip file instead of a directory. It is
also a good idea to include the zip resp. jar file containing the
basic <code>java.*</code> class files.
<pre>
export CLASSPATH=$HOME/jode_cls.zip:$HOME/download:/usr/lib/java/lib/classes.zip
</pre>
</li>
<li> Now you can start the graphical interface as following (Note the
case of the parameter)
<pre>
java jode.JodeWindow
</pre>
</li>
<li> The classpath field should already contain the classpath you set
above. The class field contains <code>jode.JodeWindow</code> and
you may push start immediately to decompile this class.
</li>
<li> If you want to decompile your own <code>.class</code> file, enter
the name of the file without <code>.class</code> extension and
push the start button. Change the class path if it doesn't point
to the right directory.
</li>
<li> After decompiling, you can save the file using the save button.
</li>
</ol>
<h1>Packaged classes</h1>
If the class file belongs to a package (like jode.JodeWindow) you
have to give the full qualified class name (the package names
separated by a dot followed by the class name). The class path should
point to the directory containing the package sub directories in this
case. <br><br>
<h1>Command line utility</h1>
There is also a command line utility which is much more powerful, but
also more difficult to use. You can start it (after setting the
classpath) with
<pre>
java jode.Decompiler
</pre>
and get a list of the supported parameters. To decompile the whole
decompiler you can use these magic lines:
<pre>
mkdir src
CLASSPATH=jode_cls.zip java jode.Decompiler --dest src \
`unzip -v jode_cls.zip|grep .class|cut -c59-|sed s/.class//|sed s?/?.?g`
</pre>
<h1>Obfuscator</h1>
So you want to protect your classes from decompiling? Well that is
your choice. You may use my obfuscator. The class files are
decompileable again (except when using -strong option, but this is
reversable by obfuscating again), but at least the information about
the names of identifiers are completely lost. <br><br>
The obfuscator is quite difficult to use (this is why I hided this
section here) and there is only a short description of the command
line parameters:
<pre>
CLASSPATH=jode_cls.zip java jode.Obfuscator
</pre>
As a hint, to obfuscate the obfuscator use the following command line:
<pre>
CLASSPATH=jode_cls.zip java jode.Obfuscator \
-cp jode_cls.zip:/usr/lib/java/lib/classes.zip -d obfuscated.zip \
-weak -revtable translate.tbl -swaporder \
-preserve jode.Obfuscator.main jode
</pre>
The options <code>-unique</code> and <code>-table</code> can be
helpful to deobfuscate obfuscated code.
</body>

@ -0,0 +1,49 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.0//EN">
<html>
<head>
<title>Using the decompiler as applet (locally)</title>
</head>
<body>
<a href="jode.html">Up</a>
<h1>Step by Step</h1>
If you want to use the applet version you need a recent Internet
Explorer or Netscape which supports java 1.1. You can also use the
appletviewer of the java development kit.
<ol>
<li> Copy <a
href="http://www.informatik.uni-oldenburg.de/~delwi/jode/jode-applet.html"
>jode-applet.html</a> into a local directory.
</li>
<li> Copy <a
href="http://www.informatik.uni-oldenburg.de/~delwi/jode/jode_cls.zip"
>jode_cls.zip</a> to the <b>same</b> directory.
</li>
<li> Copy the <code>.class</code> file or <code>zip</code> file, you
want to decompile, to that directory.
</li>
<li> Load the html file into Netscape or Internet Explorer.
</li>
<li> Set the classpath simply to `<code>.</code>' (without quotes).
You may also specify a zip or jar file here. Note that applet and
class files must be in the same directory due to security policy. <br>
You can also change the default classpath in the html file.
</li>
<li> Enter the name of the class without <code>.class</code>
extension.
</li>
<li> Press start button in applet. </li>
<li> Press save button to save the decompiled code. </li>
</ol>
<h1>Packaged classes</h1>
If the class file belongs to a package (like jode.JodeWindow) you
have to give the full qualified class name (the package names
separated by a dot followed by the class name). The class path should
point to the directory containing the package sub directories in this
case.
</body>

@ -0,0 +1,62 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.0//EN">
<html>
<head>
<title>Using the decompiler under Windows</title>
</head>
<body>
<a href="jode.html">Up</a>
<h1>Step by Step</h1>
You need java version 1.1 or higher. I suggest using the Sun JDK or
JRE 1.1 or 1.2. In the following description I assume Sun JDK 1.2,
for other virtual machines the paths and the name of the java
interpreter (<code>c:\jdk1.2\java</code>) may differ. <br><br>
<ol>
<li> Set the classpath. It should include the jode_cls.zip as well as
the directory where the class files you want to decompile resides.
You can also specify a zip file instead of a directory. It is
also a good Idea to include the zip resp. jar file containing the
basic <code>java.*</code> class files.
<pre>
set CLASSPATH=c:\temp\jode_cls.zip;c:\temp;c:\jdk1.2\jre\lib\rt.jar
</pre>
</li>
<li> Now you can start the graphical interface as following (Note the
case of the parameter)
<pre>
c:\jdk1.2\java jode.JodeWindow
</pre>
</li>
<li> The classpath field should already contain the classpath you set
above. The class field contains <code>jode.JodeWindow</code> and
you may push start immediately to decompile this class.
</li>
<li> If you want to decompile your own <code>.class</code> file, enter
the name of the file without <code>.class</code> extension and
push the start button. Change the class path if it doesn't point
to the right directory.
</li>
<li> After decompiling, you can save the file using the save button.
</li>
</ol>
<h1>Packaged classes</h1>
If the class file belongs to a package (like jode.JodeWindow) you
have to give the full qualified class name (the package names
separated by a dot followed by the class name). The class path should
point to the directory containing the package sub directories in this
case. <br><br>
<h1>Command line utility</h1>
There is also a command line utility which is much more powerful, but
also more difficult to use. You can start it (after setting the
classpath) with
<pre>
c:\jdk1.2\java jode.Decompiler
</pre>
and get a list of the supported parameters.
</body>

@ -0,0 +1,125 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.0//EN">
<html>
<head>
<title> JOchens' java-DEcompiler (JODE) </title>
<meta name="description" content="The home page of jode, my Java decompiler.">
<meta name="author" content="Jochen Hoenicke">
<meta name="keywords" content="jode, java, decompile, decompiler,
java-decompiler, reverse engineering, free, GPL">
<meta name="robots" content="index">
<meta name="robots" content="nofollow">
<meta name="date" content="1999-03-08">
</head>
<body>
<a href="http://www.informatik.uni-oldenbur.de/~delwi/jode/jode.html">
An uptodate version of this page is located here.</a><p>
<h2>What is it?</h2>
<P>This is a decompiler for java I have written in my spare time. It
takes class-files as input and produces something similar to the
original java-File. Of course this can't be perfect: There is no way
to produce the comments or the names of local variables (except when
compiled with <code>-g</code>) and there are often more ways to write
the same thing. But it does its job quite well.</P>
<h2>Quick Test</h2>
I have now an applet interface to the decompiler.
<a href="jode-applet.html">Check it out</a>.
<h2>How to get it</h2>
<P>You can donwload the files in zip form.
The <a href="jode_src.zip">sources</a> contain only the
<code>java</code> files, the <a href="jode_cls.zip">classes</a>
contain only the <code>class</code> files. </p>
<p>I also have a <a href="jode.tar.gz">tar.gz file</a> containing only
the <code>RCS</code> directories. This is the form I maintain the
project, but you probably need unix and a few tools to use them.</p>
<p>There are also some <a href="snapshot/">snapshots</a> that have new
features like inner and anonymous classes. </p>
<p><a href=".">Click here</a> to browse the files online.
</p>
<h2>How to use it</h2>
<p>I have some simple step by step pages. There are three
possibilities:
<ul>
<li> <a href="jode-useapplet.html"> Using the applet version</a>.
This can make problem due to java's security policy, but is the
simplest way and works on most platforms.
</li>
<li> If you use Windows, you should look on <a
href="jode-win.html">this page</a>.</li>
<li> Unix users should look on <a href="jode-unix.html">this page</a>.
</ul>
<h2>Known bugs</h2>
<p>There may be situations, where the code doesn't understand complex
expressions. In this many ugly temporary variables are used, but the
code should still be compileable. This does especially happen when
you compile with `-O' flag and javac has inlined some methods. </p>
<p>Sometimes this program may exit with an <code>Exception</code> or
produce incorrect code. Most time the code can't be compiled, so that
it can be easily spotted. If you have one of these problems (except
those that occur on some of the <code>jode.test</code> files, I would
be very interested in a bug report (including the <code>class</code>
file, if possible).</p>
<p>Sometimes it generates some <code>GOTO</code> expression and
labels. This can't be compiled, but shouldn't happen any more with
javac or jikes.</p>
<p>It doesn't handle inner and anonymous classes, yet. You can
decompile them separately, though (use `<code>+$</code>' switch under
jikes), but there is a bug in javac, so that a final variable is twice
initialized. If you encounter this problem just remove the doubled
line by hand. </p>
<p><b>New!</b> The latest <a href="snapshot">snapshot</a> can handle
inner and anonymous classes.</p>
<h2>Why did I wrote it?</h2>
<p>Someday I found <code>guavad</code>, a disassembler for java byte
code (it does similar things like <code>javap&nbsp;-c</code>). I used
it on a class file, and found that it was possible to reconstruct the
original java code. First I did it by hand on some small routines,
but I soon realized that it was a rather stupid task, and that I could
write a <a href="../perl/dasm_to_java.perl"><code>perl</code> script</a>
that does the same. At the end of the next day I had a working
decompiler.</p>
<p>Now while it was working, it was not easy to use. You had to
decompile the code first with a disassembler, cut the method, you
wanted to decompile and then run the perl script on it. So I decided
to get some information of the class files and do this all
automatically. I decided to write it in <code>java</code> now,
because it suited best.</p>
<p>Just for the records: the java code is now more than 50 times
bigger than the original perl script and is still growing.</p>
<h2>License</h2>
<p>This code is under GNU GPL. That basically means, that you can copy
or modify this code, as long as you put all your modification under
the GPL again. <A HREF="http://www.gnu.org/copyleft/gpl.html"> Look
here for the complete license</a>.</p>
<hr>
<p><A HREF="mailto:Jochen.Hoenicke@Informatik.Uni-Oldenburg.DE">
http://www.informatik.uni-oldenburg.de/~delwi/jode/jode.html</A>, last
updated on <em>17-Jun-1999</em>.</p>
</body>
</html>

@ -1,67 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Java Optimize and Decompile Environment (JODE)</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="date" content="2001-05-29">
<meta name="description" content="JODE - Java Optimize and Decompile Environment.">
<meta name="author" content="Jochen Hoenicke">
<meta name="keywords" content="jode, java, decompiler, obfuscator, deobfuscator, reverse engineering, free, GPL">
<style type="text/css">
<!--
body { color:#000000; background-color: #FFFFFF; }
.nav { font-family: Helvetica, Arial, sans-serif; font-weight: bold;
color:#000000; background-color: #EEEEF8; }
.footer { color:#FFFFFF; background-color: #737B9C; }
.boldlink { font-weight:bold; text-decoration: none; color:#FFFFFF; }
//-->
</style>
</head>
<body text="#000000" bgcolor="#FFFFFF">
<table cellpadding=4 cellspacing=1 width="100%"
><tr
><td align="left"
><img src="jode-logo.png" alt="JODE"
></td
><td align="right"
>Powered by <a href="http://sourceforge.net"><img
src="http://sourceforge.net/sflogo.php?group_id=3790&amp;type=1"
border=0 width=88 height=31 alt="SourceForge"></a><br
>HTML coding <a href="http://htp.sourceforge.net"><img
src="poweredbyhtp.png" border=0 alt="Powered by htp"></a><br
>Best viewed with <a
href="http://www.anybrowser.org/campaign/"><img
src="w3c_ab.png" border=0 alt="Any Browser"></a><br
></td
></tr
></table>
<table cellspacing=0 cellpadding=3 border=0 bgcolor="#EEEEF8" class="nav">
<tr><td class="nav">
<use menu>
</td></tr>
</table><br>
<use everything>
<if _htpfile_out="index.html">
<set pageref="">
<else>
<set pageref="$_htpfile_out">
</if>
<TABLE class=footer width="100%" border="0" cellspacing="0" cellpadding="2">
<TR>
<TD align="center"><SPAN class=footer>
All trademarks and copyrights on this page are properties of their respective owners. <br>
Last updated on <file date>,
Copyright &copy; 1998-2004 by Jochen Hoenicke.
Canonic URL is <a class=boldlink href="http://jode.sourceforge.net/$pageref">http://jode.sourceforge.net/<use pageref></a></SPAN>
</TD>
</TR>
</TABLE>
</BODY>
</HTML>

@ -1,21 +0,0 @@
<section title="License">
<p><i>JODE</i> is Copyright &copy; 1998-2004 by Jochen Hoenicke. <br><br>
<p>This program is free software; you can redistribute it and/or modify
it under the terms of the <a
href="http://www.gnu.org/copyleft/gpl.html">GNU General Public
License</a> as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.</p>
<p>You can redistribute some of the packages under the
terms of the of the <a
href="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General
Public License</a> as published by the Free Software Foundation. See
the copyright headers in the source code.</p>
<p>This program is distributed in the hope that it will be useful,
but <b>without any warranty</b>; without even the implied warranty of
<b>merchantability</b> or <b>fitness for a particular purpose</b>. See the
GNU General Public License for more details.</p>
</section>

@ -1,75 +0,0 @@
<section title="<i>JODE</i> Links">
<h3>Other decompilers</h3>
<ul>
<li><a href="http://dmoz.org/Computers/Programming/Languages/Java/Development_Tools/Translators/Decompilers_and_Disassemblers/">The Open Directory list</a></li>
<li>A list of decompilers can be found at <a href="http://www.meurrens.org/ip-Links/Java/CodeEngineering/#tocDecompilersToJava">Marc Meurren's list</a>
</li>
<li>A very fast decompiler is <a
href="http://www.geocities.com/SiliconValley/Bridge/8617/jad.html">jad</a>
written in C++. It doesn't come with source code though, and misses
some features <i>JODE</i> has ;-)</li> <li><a
href="http://www.javaworld.com/javaworld/jw-07-1997/jw-07-decompilers.html">A
comparison of three decompilers</a> (but not <i>JODE</i>) was done by Dave
Dyer.
</ul>
<h3>Other obfuscators</h3>
<ul>
<li><a href="http://dmoz.org/Computers/Programming/Languages/Java/Development_Tools/Obfuscators/">The Open Directory list</a></li>
<li><a href="http://www.sbktech.org/hashjava_old.html">Hashjava</a> is another free obfuscator. It is no longer maintained, though, since its successor was commercialized.</li>
<li><a href="http://www.zelix.com/klassmaster/index.html">Zelix
Klassmaster</a> does a very good flow optimization and also decrypts
strings. But <i>JODE</i>'s deobfuscator can undo both.</li>
<li><a href="http://www.cs.arizona.edu/~collberg/Research/">Christian S. Collberg</a> has some really interesting papers about non reversible obfuscations.</li>
</ul>
<h3>Graphical User Interface</h3>
<ul>
<li><i>JODE</i> is used by the <a
href="http://jedit.standmed.com/plugins/JavaInsight">JavaInsight plugin</a> for
<a href="http://jedit.sourceforge.net/">jEdit</a>.</li>
</ul>
<h3>Software Directories</h3>
<ul>
<li>Get everything and anything for Linux at the
<a href="http://www.linux-directory.com" target="_top"
><IMG SRC="http://www.linux-directory.com/button_88x31.gif"
WIDTH=88 HEIGHT=31 BORDER=0 ALT="Linux Directory"></a>.
</li>
<li>A great place for developing free software is
<a href="http://sourceforge.net"><img
src="http://sourceforge.net/sflogo.php?group_id=3790&type=1"
border=0 width=88 height=31 alt="SourceForge"></a>
</li>
</ul>
<h3>Miscellanous packages needed to run JODE</h3>
<dl>
<dt>CYGWIN (unix tools for win95/NT)</dt>
<dd>
<a href="http://sourceware.cygnus.com/cygwin/">http://sourceware.cygnus.com/cygwin/</a>
</dd>
<dt>JDK 1.1:</dt>
<dd>
<a href="http://java.sun.com/products/jdk/1.1/">http://java.sun.com/products/jdk/1.1/</a>
</dd>
<dt><a name="swing">Swing for JDK 1.1:</a><dt>
<dd>
<a href="http://java.sun.com/products/jfc/index.html#download-swing">http://java.sun.com/products/jfc/index.html#download-swing</a>
</dd>
<dt>JDK 1.2:</dt>
<dd>
<a href="http://java.sun.com/products/jdk/1.2/">http://java.sun.com/products/jdk/1.2/</a>
</dd>
<dt><a name="getopt">Getopt</a>:</dt>
<dd>
<a href="http://www.urbanophile.com/arenn/hacking/download.html#getopt">http://www.urbanophile.com/arenn/hacking/download.html#getopt</a>
</dd>
<dt><a name="collections">Collection Classes</a>:</dt>
<dd>I have written a small script that puts the collection classes
from the <a href="http://www.classpath.org">GNU Classpath Project</a>
into its own package (<code>gnu.java.util.collections</code>). This
script is now part of GNU classpath. For your convenience I have put a
precompiled <a
href="http://www.informatik.uni-oldenburg.de/~delwi/jode/collections.jar">jar
file</a> on this server.
</dd>
</dl>
</section>

@ -1,47 +0,0 @@
<?php
$menu =
array("<B>Home</B>" , "selflink", "index",
"Project page" , "sflink", "project/",
"Applet" , "selflink", "applet",
"Download" , "selflink", "download",
"FAQ" , "selflink", "faq",
"Feedback" , "selflink", "feedback",
"Documentation", "selflink", "usage",
"License" , "selflink", "license",
"History" , "selflink", "history",
"Links" , "selflink", "links",
"Blue Sky" , "selflink", "bluesky");
?>
<table cellspacing=0 cellpadding=3 border=0 bgcolor="#EEEEF8" class="nav">
<tr><td class="nav">
<?php
reset($menu);
$self = ereg_replace("^.*/", "", $PHP_SELF);
while (list($dummy, $name) = each($menu)) {
list($dummy, $type) = each($menu);
list($dummy, $link) = each($menu);
$name = ereg_replace(" ", "&nbsp;", $name);
if ($type == "selflink") {
if ($self == "$link.$extension") {
echo "$name";
} else {
selflink($link);
echo "$name</a>";
}
} else if ($type == "sflink") {
sflink($link);
echo "$name</a>";
} else if ($type == "-") {
echo "<br>\n";
continue;
} else if ($type == "link") {
echo "<a href=\"$link\">$name</a>";
}
if (current($menu)) {
echo " |\n";
}
}
?>
</td></tr>
</table><br>

@ -1,84 +0,0 @@
# This is a sample script file to obfuscate my project
# The class path should include everything that is needed to run the
# project. Don't forget the java base classes (rt.jar or classes.zip).
classpath = "c:\\jdk1.2\\jre\\lib\\rt.jar","d:\\project\\java"
# The jar, zip file or directory in which the obfuscated class files
# should be written.
dest = "obfuscated.zip"
# Write the reverse translation table to translat.tbl. With the help of
# this table you can later undo the renaming.
revtable = "translat.tbl"
strip = "unreach","lvt","inner"
# this variable will tell, which classes and packages should be included
# in the obfuscated.jar package.
load = new WildCard { value = "org.myorg.myproject" },
new WildCard { value = "org.myorg.mylib*" },
new WildCard { value = "org.otherorg.shortlib" }
# this variable will tell, which classes and packages must not be
# renamed.
preserve = new WildCard { value = "org.myorg.ApplicationClass.main.*" },
new WildCard { value = "org.myorg.AppletClass.<init>.()V" },
new WildCard { value = "org.resources.BundleClass*.<init>.()V" },
new MultiIdentifierMatcher {
and = new WildCard { value = "org.myorg.publiclib.*" },
new ModifierMatcher { access = "PUBLIC" }
}
# There are different renamers currently. This is just an example that
# produces very good obfuscated code, that is still valid bytecode.
renamer = new StrongRenamer {
charsetStart = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"
charsetPart = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789_$"
charsetPackage = "abcdefghijklmnopqrstuvwxyz"
charsetClass = "abcdefghijklmnopqrstuvwxyz"
}
# The constant analyzer does a great job to remove constant fields and
# deadcode. E.g. if you obfuscate the decompiler applet it will
# remove the whole debugging code, since the applet doesn't need it.
analyzer = new ConstantAnalyzer
# The LocalOptimizer will reorder local variables to use fewer slots.
# It may still have some bugs, so remove it if your applet doesn't
# work (and send me the class).
# The RemovePopAnalyzer will remove instructions that were optimized
# away by the ConstantAnalyzer and LocalOptimizer.
post = new LocalOptimizer, new RemovePopAnalyzer
################################################################
# The syntax for load and preserve is as follows
################################################################
#
# preserve ::= <list of IdentifierMatcher>
# // preserves everything that is matched by
# // at least one identifier matcher.
#
# IdentifierMatcher ::=
# MultiIdentifierMatcher { and = <list of IdentifierMatcher> }
# |
# MultiIdentifierMatcher { or = <list of IdentifierMatcher> }
# |
# WildCard { value = "<wildcard>" }
# |
# ModifierMatcher { access = "<AccessSpec>"
# [access = "<AccessSpec>" ...]
# modifier = "<ModifierSpec>"
# [modifier = "<ModifierSpec>" ...]
# // identifier must fulfill all constraints
# }
# |
# SerializedPreserver
#
# AccessSpec ::=
# <optional "<" or ">"> (PUBLIC|PROTECTED|PACKAGE|PRIVATE)
#
# ModifierSpec ::=
# <optional "!" (not)> (ABSTRACT|FINAL|INTERFACE|NATIVE|STATIC
# |STRICT|SYNCHRONIZED|TRANSIENT|VOLATILE)
#

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

@ -215,65 +215,3 @@ Zu betrachtende 32bit Typen:
(I,S,B,Z)
(I,S,B,cS,cB)
@node Highlevel analysis, Technical Info, Solving unknown stack-ops, Technical Info
@section Highlevel analysis
@cindex passes
@section The passes
JODE works in three passes:
@subsection Pass 1: Initialize
In the initialize pass the methods, fields and inner classes are read in
and the inner classes are recursively initialized. In this pass the
complexity of the class is calculated. Anonymous and method scoped
classes aren't even considered yet.
@subsection Pass 2: Analyze
The analyze pass is the real decompilation pass: The code of the methods
is transformed into flow blocks and merged to one flow block as
described in a previous section. The in/out analysis for the local
variables is completed, and the locals are merged as necessary. The
parameter 0 for non static method is marked as ThisOperator in this
pass.
The constructors are analyzed first. If they initialize synthetic
fields, this is taken as clear sign that this are outer value
parameters. So afterwards, these synthetic fields know their value.
Then the methods are analyzed. Each method remembers the anonymous
classes it creates for Pass 3, but these classes are not yet
initialized. Inner classes aren't analyzed yet, either.
@subsection Pass 3: Analyze Inner
As the name of this pass makes clear the inner classes are initialized
in this pass, i.e. first Pass 2 and 3 are invoked for the inner classes.
After that the method scoped classes are analyzed: For each constructor
it is first check if one surrounding method knows about it. If not, a
new class analyzer is created for the method scoped class and Pass 1--3
are invoked. Every surrounding method is then told about this new class
analyzer.
After this pass, every anonymous constructor is analyzed, so we know
which constructor parameters can be outer values. The constructor
transformation may force some other outer values, though. It is also
known, in which method a method scoped class must be declared.
@subsection Pass 4: Make Declarations
The last pass begins with transforming the constructors of a class. Now
the outer values are fixed and the constructor parameters and synthetic
fields are told their values.
After that every method determines where to declare local variables and
method scoped classes. Local variables are declared as final if a
method scoped class uses it as outer value. The name of local
variables is guessed now.
This pass is done recursively for inner and method scoped classes.

@ -1,250 +0,0 @@
<if we_want_a_menu>
<p>On this page:<br>
<a href="#decompiler">Decompiler</a><br>
&nbsp;&nbsp;&nbsp;<a href="#cmdline">Command&nbsp;Line</a><br>
&nbsp;&nbsp;&nbsp;<a href="#awt">AWT&nbsp;Interface</a><br>
&nbsp;&nbsp;&nbsp;<a href="#swing">Swing&nbsp;Interface</a><br>
&nbsp;&nbsp;&nbsp;<a href="#java">Java&nbsp;Interface</a><br>
<a href="#optimizer">Obfuscator</a><br>
</p>
</if>
<section title="Using the Decompiler">
<p>After you have <a href="download.html">downloaded</a> the jar archive
put it into your <tt>CLASSPATH</tt>. The package
<tt>swingall.jar</tt> is also needed if you are using JDK 1.1.</p>
<ul><li>Under Windows you have to start a MSDOS session and type
something like:
<pre>
set CLASSPATH=C:\download\jode-<use version>.jar;C:\swing\swingall.jar
</pre>
<li>Under Unix you start a shell and type (for bourne shell):
<pre>export CLASSPATH=/tmp/jode-<use version>.jar:/usr/local/swing/swingall.jar</pre>
or for csh:
<pre>setenv CLASSPATH /tmp/jode-<use version>.jar:/usr/local/swing/swingall.jar</pre>
</ul>
<br>
There is also a batch file for windows and a script file for unix,
that you can use. You can extract it with the following command:
<pre>
jar -xvf jode-<use version>".jar bin/jode.bat <i>resp.</i> bin/jode
</pre>
Edit the file to adapt it to your paths and put it to a convenient location.
</section>
<section title="Command Line Interface">
The most powerful way to start <I>JODE</I>'s decompiler is the command
line interface. Some people don't like long command lines; they
should go to the next section. <br>
Start the class <tt>jode.decompiler.Main</tt> with the options. The
following command will give a complete list of the available commands:
<pre>java jode.decompiler.Main --help</pre>
If you want to decompile a jar package you can do it this way:
<pre>java jode.decompiler.Main --dest srcdir program.jar</pre>
If you have installed the batch file/script, you can use it like this:
<pre>jode --dest srcdir program.jar</pre>
<h3><a name="awt">AWT Interface</a></h3>
The AWT Interface looks exactly like the <a href="applet.html">
applet</a>. In fact the applet uses the AWT Interface. You start it
after setting the <tt>CLASSPATH</tt> (see <a
href="#decompiler">above</a>), with
<pre>java jode.decompiler.Window</pre>
In the classpath line you can enter a number of jar files, zip files
and directories separated by comma(<tt>,</tt>). Then enter the
dot(<tt>.</tt>) separated name of the class you want to decompile.
Press the <code>start</code> button and the decompiled class should
appear. You can save it via the <code>save</code> button.
<h3><a name="swing">Swing Interface</a></h3>
For the swing interface you need java version 1.2 or the separately
available swing package (see <a href="links.html#swing">link
page</a>. You can invoke it with the following command (JDK1.2 only):
<pre>
java -jar jode-<use version>.jar classes.jar
</pre>
or if you have set the classpath (see above)
<pre>
java jode.swingui.Main classes.jar
<i>resp.</i> jode swi classes.jar
</pre>
<p>The swing interface will show the package hierarchie of all classes
in the classpath on the left side. You can now select a class and the
decompiled code will appear on the right side. Via the menu, you may
change the classpath or switch between package hierarchie tree and
class inheritence tree.</p>
<p>The swing interface is very useful to browse through class files if
you don't have the source code. You can also use it to trace bugs in
library code. It is not meant to generate <tt>java</tt> files and so
you won't find a save option there.</p>
<h3><a name="java">Java Interface</a></h3>
<p>If you want to integrate <i>JODE</i> into your own java program,
you can use the <a
href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/jode/jode/jode/decompiler/Decompiler.java?rev=jode_1_1&amp;content-type=text/vnd.viewcvs-markup"
><code>jode.decompiler.Decompiler</code></a>
class. Note that the LGPL allows dynamic linking as long as you don't change
Jode itself. Please tell me if you use <i>JODE</i> in this way.</p>
<p>You should ship <code>jode-1.1-embedded.jar</code> with your program. This jar file is
available in the <sflink href="project/showfiles.php">download area</a>.
It works only under JDK&nbsp;1.2 and above.</p>
</section>
<section title="Using the Obfuscator">
<p>To use the obfuscator you should first create a script file, say <a
href="myproject.jos"><tt>myproject.jos</tt></a>. Then you can invoke the
obfuscator with:</p>
<pre>
java jode.obfuscator.Main myproject.jos
</pre>
<p>The script file should contain the following options: </p>
<p>First select the classpath. You should include everything in the
classpath that you need to run your application. This also includes
the system class files (Sun puts them into <code>classes.zip</code> or
<code>rt.jar</code>))</p>
<pre>
classpath = "c:\\jdk1.2\\jre\\lib\\rt.jar","d:\\project\\java",
"ftp://www.myorg.org/pub/classlib.jar"
</pre>
<p>Specify where you want the obfuscated classes to go. I recommend
to write them directly into a zip file, but you can also give a
directory.</p>
<pre>
dest = "obfuscated.zip"
</pre>
<p>You can make <i>JODE</i> write its translation table. This table
can be used later to undo the name obfuscation, or you can look there
to decrypt exceptions you may get.</p>
<pre>
revtable = "translat.tbl"
</pre>
<p>Select what you want to strip. There are several
possibilities, which can be separated by comma(<tt>,</tt>):</p>
<dl>
<dt>unreach</dt>
<dd>strip unreachable methods and classes.</dd>
<dt>source</dt>
<dd>remove the name of the java file (exceptions will get unreadable).</dd>
<dt>lnt</dt>
<dd>remove the line number table (exceptions will get unreadable).</dd>
<dt>lvt</dt>
<dd>remove the local variable table (debugging doesn't work).</dd>
<dt>inner</dt>
<dd>strip inner class info (reflection doesn't work correctly).</dd>
</dl>
<pre>
strip = "unreach","lvt","inner"
</pre>
<p>Select the packages and classes you want to obfuscate. You should
only include libraries, that you don't ship separately. If you give a
package, all classes and subpackages are loaded. You can also use
<code>*</code> as wild card, that matches everything (including dots).
</p>
<pre>
load = new WildCard { value = "org.myorg.myproject" },
new WildCard { value = "org.myorg.mylib*" },
new WildCard { value = "org.otherorg.shortlib" }
</pre>
<p>Select the methods and classes you want to preserve. This is
the <tt>main</tt> method for applications and the default constructor
<tt>&lt;init&gt;.()V</tt> for applets, resource bundles and other classes
that you load manually at runtime. <br>
You have to give the method
name and the type signature to identify your method. <tt>javap
-s</tt> will show you the type signatures for your classes, but you
may also use <tt>*</tt>, to select all methods with that name.
If you have serializable classes and want to preserve their serialized
form you can use the <tt>SerializePreserver</tt>. </p>
<pre>
preserve = new SerializePreserver,
new WildCard { value = "org.myorg.ApplicationClass.main.*" },
new WildCard { value = "org.myorg.AppletClass.&lt;init&gt;.()V" },
new WildCard { value = "org.resources.Bundle*.&lt;init&gt;.()V" },
</pre>
<p>If you want to obfuscate (or just shorten) the identifier you can
specify a renamer. There are currently following renamer
available</p>
<dl><dt>StrongRenamer</dt>
<dd>Renames to the shortest possible name. You can give a charset
that should be used. It uses the same name as much as possible.</dd>
<dt>UniqueRenamer</dt>
<dd>Renames to unique identifier of the form <tt>xxx123</tt>. Useful
to reduce name conflicts, before you decompile an obfuscated package.</dd>
<dt>NameSwapper</dt>
<dd>This renamer just swaps the names. This is a funny obfuscation
option that is not very strong, but very confusing.</dd>
<dt>KeywordRenamer</dt>
<dd>Renames identifiers to keyword. You can give your own list of
keywords as parameters. Resulting code is not decompilable directly,
<b>but it is <i>not</i> legal bytecode either</b>. Some paranoid
web browsers refuse to run applets containing keywords as identifiers
(and they are completely within the Java VM spec).</dd>
</dl>
<pre>
renamer = new StrongRenamer
</pre>
<p>You can also create a renaming table with the same format as the
table written by revtable. The entries in the table get precedence
over renamer. Entries not in the table will get renamed by the
renamer.</p>
<pre>
table = "translat.tbl"
</pre>
<p>Now you can select the analyzer. The purpose of the
analyzer is to mark all reachable methods, find out which methods
needs to get the same name (overloading), and which method names
mustn't change (overload of library methods, e.g. <tt>nextElement</tt>
for <tt>Enumeration</tt>s). There are currently two analyzers.
</p>
<dl><dt>SimpleAnalyzer</dt>
<dd>Straight forward analyzer. It is fast and will remove dead code
on method basis.</dd>
<dd><dt>ConstantAnalyzer</dt>
<dd>Strong analyzer that will determine, which fields and instructions
have constant values. It will remove dead code on instruction basis
and replace constant instruction with a load of the constant, or
remove them completely.<br> This analyzer is especially useful to
revert the flow obfuscation of some other obfuscators.</dd>
</dl>
<pre>
analyzer = new ConstantAnalyzer
</pre>
<p>Pre- and Post transformers transform the bytecode before
resp. after the Analyzer runs. Using this default should be okay.
You may remove the LocalOptimizer, though, if you have problems.</p>
<p>In the future I may add some new post transformers, that do string
encryption, flow obfuscation and similar things. If you want to write
your own Transformers please contact me, since the next version will
change the bytecode interface.</p>
<pre>
post = new LocalOptimizer, new RemovePopAnalyzer
</pre>
</section>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

@ -1,6 +1,6 @@
#!/usr/bin/perl -w
#!/usr/bin/perl
#
# jcpp Copyright (C) 1999-2001 Jochen Hoenicke.
# jcpp Copyright (C) 1999 Jochen Hoenicke.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -23,9 +23,8 @@
# preprocessor, but to modify the java files directly and make use of
# comments.
#
# The comments all have the form /// and start at the beginning of the
# line to distinguish them from normal comments. You must not use
# such comments for other purposes.
# The comments all have the form /// to distinguish them from normal
# comments. You should not use such comments yourself.
#
# Usage is simple: jcpp -Ddefine1 -Ddefine2 first.java second.java
# The files should contain comments of the form
@ -38,23 +37,6 @@
#
# After running jcpp the false branch is commented out. If the true
# branch was commented out it will get commented in.
#
# jcpp can also change definitions, useful for package renaming. The
# java file should look like this:
#
# ///#def COLLECTIONS java.util
# import java.util.Vector
# import java.util.ArrayList
# ///#enddef
#
# If jcpp is then called with -DCOLLECTIONS=gnu.java.util.collections
# it will replace every occurence of java.util (the string in the #def
# line) with the new value:
#
# ///#def COLLECTIONS gnu.java.util.collections
# import gnu.java.util.collections.Vector
# import gnu.java.util.collections.ArrayList
# ///#enddef
my @files;
my %defs;
@ -85,11 +67,6 @@ for (@files) {
my $error = 0;
my $changes = 0;
# The list of #def replacements, @replold is the previous value,
# @replnew the new one.
my @replold = ();
my @replnew = ();
my $file = $_;
open OLD, "<$file" or do {
print STDERR "Can't open file $file\n";
@ -105,9 +82,10 @@ for (@files) {
$linenr++;
if (m'^///#') {
# This is a directive. First we print it out.
if (m'^///#\s*if') {
print NEW $_;
if (m'^///# *if') {
$level++;
if (m'^///#\s*ifdef\s+(\w+)\s*$') {
if (m'^///# *ifdef (\S*)$') {
# If there was an outer false #if directive, we ignore the
# condition.
next LINE if ($falselevel);
@ -117,7 +95,7 @@ for (@files) {
# An ifdef directive, look if -D is defined.
$falselevel = $level
unless (defined $defs{$label});
} elsif (m'^///#\s*ifndef\s+(\w+)\s*$') {
} elsif (m'^///# *ifndef (\S*)$') {
# If there was an outer false #if directive, we ignore the
# condition.
next LINE if ($falselevel);
@ -126,34 +104,8 @@ for (@files) {
# An ifndef directive, look if -D is defined
$falselevel = $level
if (defined $defs{$label});
} elsif (m'^///#\s*if\s+(\w+)\s*(==|!=)\s*(\S+)\s*$') {
# If there was an outer false #if directive, we ignore the
# condition.
next LINE if ($falselevel);
my $label=$1;
my $value=$3;
# An ifdef directive, look if -D is defined.
$falselevel = $level
unless ($2 eq "==" ? $defs{$label} eq $value
: $defs{$label} ne $value);
} elsif (m'^///#\s*if\s+(\w+)\s*(>=|<=|>|<)\s*(\S+)\s*$') {
# If there was an outer false #if directive, we ignore the
# condition.
next LINE if ($falselevel);
my $label=$1;
my $value=$3;
# An ifdef directive, look if -D is defined.
$falselevel = $level
unless ($2 eq ">=" ? $defs{$label} >= $value
: $2 eq "<=" ? $defs{$label} <= $value
: $2 eq ">" ? $defs{$label} > $value
: $defs{$label} < $value);
}
} elsif (m'^///#\s*else\s*$') {
} elsif (m'^///# *else') {
# An else directive. We switch from true to false and
# if level is falselevel we switch from false to true
if ($level == 0) {
@ -165,7 +117,7 @@ for (@files) {
} elsif ($falselevel == 0) {
$falselevel = $level;
}
} elsif (m'^///#\s*endif\s*$') {
} elsif (m'^///# *endif') {
# set $falselevel to 0, if the false branch is over now.
$falselevel = 0 if ($falselevel == $level);
# decrease level.
@ -175,21 +127,6 @@ for (@files) {
} else {
$level--;
}
} elsif (m'^///#\s*def\s+(\w+)\s+(\S*)$') {
my $label = $1;
my $old = $2;
my $new = $defs{$label};
if (defined $new && $new ne $old) {
push @replold, "$old";
push @replnew, "$new";
$changes = 1;
} else {
push @replnew, "";
push @replold, "";
}
} elsif (m'^///#\s*enddef\s*$') {
pop @replold;
pop @replnew;
} else {
print STDERR "$file: $linenr: ignoring unknown directive $_";
$error = 1;
@ -198,20 +135,21 @@ for (@files) {
$line = $1;
if ($falselevel == 0 && $level > 0) {
# remove comments in true branch, but not in outermost level.
$_ = "$line\n";
print NEW "$line\n";
$changes = 1;
} else {
# print out the full line with comments:
print NEW $_;
}
} else {
if ($falselevel != 0) {
# add comments in false branch
$_ = "///$_";
print NEW "///$_";
$changes = 1;
} else {
print NEW $_;
}
}
for ($i = 0; $i < @replold; $i++) {
$_ =~ s/\Q$replold[$i]\E/$replnew[$i]/ if ($replold[$i] ne "");
}
print NEW $_;
}
if ($level != 0 || $falselevel != 0) {
@ -225,7 +163,8 @@ for (@files) {
if ($changes == 0) {
unlink "$file.tmp";
} else {
(unlink "$file" and rename "$file.tmp", "$file")
(rename "$file", "$file.orig"
and rename "$file.tmp", "$file")
or print STDERR "$file: Couldn't rename files.\n";
}
} else {

@ -0,0 +1,4 @@
Makefile
Makefile.in
.java.deps
jode.jar

@ -1,4 +1,4 @@
/* ParseException Copyright (C) 1999-2002 Jochen Hoenicke.
/* AssertError Copyright (C) 1998-1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -17,10 +17,13 @@
* $Id$
*/
package net.sf.jode.obfuscator;
package jode;
public class ParseException extends Exception {
public ParseException(int linenr, String message) {
super ("line "+linenr+": "+message);
public class AssertError extends Error {
public AssertError() {
}
public AssertError(String detail) {
super(detail);
}
}

@ -0,0 +1,284 @@
/* Decompiler Copyright (C) 1998-1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package jode;
import java.io.*;
import jode.bytecode.ClassInfo;
import jode.bytecode.SearchPath;
import jode.bytecode.InnerClassInfo;
import jode.decompiler.*;
import java.util.zip.ZipOutputStream;
import java.util.zip.ZipEntry;
public class Decompiler {
public final static int TAB_SIZE_MASK = 0x0f;
public final static int BRACE_AT_EOL = 0x10;
public final static int SUN_STYLE = 0x14;
public final static int GNU_STYLE = 0x02;
public static final int OPTION_LVT = 0x0001;
public static final int OPTION_INNER = 0x0002;
public static final int OPTION_ANON = 0x0004;
public static final int OPTION_PUSH = 0x0008;
public static final int OPTION_PRETTY = 0x0010;
public static final int OPTION_DECRYPT = 0x0020;
public static final int OPTION_ONETIME = 0x0040;
public static final int OPTION_IMMEDIATE = 0x0080;
public static final int OPTION_VERIFY = 0x0100;
public static final int OPTION_CONTRAFO = 0x0200;
public static int options =
OPTION_LVT | OPTION_INNER | OPTION_ANON |
OPTION_DECRYPT | OPTION_VERIFY | OPTION_CONTRAFO;
public static final String[] optionNames = {
"lvt", "inner", "anonymous", "push",
"pretty", "decrypt", "onetime", "immediate",
"verify", "contrafo"
};
public static int outputStyle = SUN_STYLE;
public static void usage() {
PrintWriter err = GlobalOptions.err;
err.println("Version: " + GlobalOptions.version);
err.print("use: jode [-v]"
+"[--cp <classpath>][--dest <destdir>]"
+"[--import <pkglimit> <clslimit>]");
for (int i=0; i < optionNames.length; i++)
err.print("[--[no]"+optionNames[i]+"]");
err.println("[--debug=...] class1 [class2 ...]");
err.println("\t-v "+
"be verbose (multiple times means more verbose).");
err.println("\t--cp <classpath> "+
"search for classes in specified classpath.");
err.println("\t "+
"The paths should be separated by ','.");
err.println("\t--dest <destdir> "+
"write decompiled files to disk into directory destdir.");
err.println("\t--style {sun|gnu}"+
" specifies indentation style");
err.println("\t--import <pkglimit> <clslimit>");
err.println("\t "+
"import classes used more than clslimit times");
err.println("\t "+
"and packages with more then pkglimit used classes");
err.println("\t--[no]inner "+
"[don't] decompile inner classes.");
err.println("\t--[no]anonymous "+
"[don't] decompile anonymous classes.");
err.println("\t--[no]contrafo "+
"[don't] transform constructors of inner classes.");
err.println("\t--[no]lvt "+
"[don't] use the local variable table.");
err.println("\t--[no]pretty "+
"[don't] use `pretty' names for local variables.");
err.println("\t--[no]push "+
"[replace] PUSH instructions [with compilable code].");
err.println("\t--[no]decrypt "+
"[don't] try to decrypt encrypted strings.");
err.println("\t--[no]onetime "+
"[don't] remove locals, that are used only one time.");
err.println("\t--[no]immediate "+
"[don't] output source immediately with wrong import.");
err.println("\t--[no]verify "+
"[don't] verify code before decompiling it.");
err.println("Debugging options, mainly used to debug this decompiler:");
err.println("\t--debug=... "+
"use --debug=help for more information.");
}
public static boolean skipClass(ClassInfo clazz) {
InnerClassInfo[] outers = clazz.getOuterClasses();
if (outers != null) {
if (outers[0].outer == null) {
return ((Decompiler.options & Decompiler.OPTION_ANON) != 0);
} else {
return ((Decompiler.options & Decompiler.OPTION_INNER) != 0);
}
}
return false;
}
public static void main(String[] params) {
int i;
String classPath = System.getProperty("java.class.path")
.replace(File.pathSeparatorChar, SearchPath.pathSeparatorChar);
File destDir = null;
ZipOutputStream destZip = null;
int importPackageLimit = ImportHandler.DEFAULT_PACKAGE_LIMIT;
int importClassLimit = ImportHandler.DEFAULT_CLASS_LIMIT;;
GlobalOptions.err.println(GlobalOptions.copyright);
for (i=0; i<params.length && params[i].startsWith("-"); i++) {
if (params[i].equals("-v"))
GlobalOptions.verboseLevel++;
else if (params[i].equals("--dest"))
destDir = new File(params[++i]);
else if (params[i].startsWith("--debug")) {
String flags;
if (params[i].startsWith("--debug=")) {
flags = params[i].substring(8);
} else if (params[i].length() != 7) {
usage();
return;
} else {
flags = params[++i];
}
GlobalOptions.setDebugging(flags);
} else if (params[i].equals("--style")) {
String style = params[++i];
if (style.equals("sun"))
outputStyle = SUN_STYLE;
else if (style.equals("gnu"))
outputStyle = GNU_STYLE;
else {
GlobalOptions.err.println("Unknown style: "+style);
usage();
return;
}
} else if (params[i].equals("--import")) {
importPackageLimit = Integer.parseInt(params[++i]);
importClassLimit = Integer.parseInt(params[++i]);
} else if (params[i].equals("--classpath")) {
classPath = params[++i];
} else if (params[i].equals("--cp")) {
classPath = params[++i];
} else if (params[i].equals("--")) {
i++;
break;
} else {
if (params[i].startsWith("--")) {
boolean negated = false;
String optionName = params[i].substring(2);
if (optionName.startsWith("no")) {
optionName = optionName.substring(2);
negated = true;
}
int index = -1;
for (int j=0; j < optionNames.length; j++) {
if (optionNames[j].startsWith(optionName)) {
if (optionNames[j].equals(optionName)) {
index = j;
break;
}
if (index == -1) {
index = j;
} else {
index = -2;
break;
}
}
}
if (index >= 0) {
if (negated)
options &= ~(1<< index);
else
options |= 1 << index;
continue;
}
}
if (!params[i].startsWith("-h") && !params[i].equals("--help"))
GlobalOptions.err.println("Unknown option: "+params[i]);
usage();
return;
}
}
if (i == params.length) {
usage();
return;
}
ClassInfo.setClassPath(classPath);
ImportHandler imports = new ImportHandler(importPackageLimit,
importClassLimit);
TabbedPrintWriter writer = null;
if (destDir == null)
writer = new TabbedPrintWriter(System.out, imports);
else if (destDir.getName().endsWith(".zip")) {
try {
destZip = new ZipOutputStream(new FileOutputStream(destDir));
} catch (IOException ex) {
GlobalOptions.err.println("Can't open zip file "+destDir);
ex.printStackTrace(GlobalOptions.err);
return;
}
writer = new TabbedPrintWriter(new BufferedOutputStream(destZip),
imports, false);
}
for (; i< params.length; i++) {
try {
ClassInfo clazz;
try {
clazz = ClassInfo.forName(params[i]);
} catch (IllegalArgumentException ex) {
GlobalOptions.err.println
("`"+params[i]+"' is not a class name");
continue;
}
if (skipClass(clazz))
continue;
String filename =
params[i].replace('.', File.separatorChar)+".java";
if (destZip != null) {
writer.flush();
destZip.putNextEntry(new ZipEntry(filename));
} else if (destDir != null) {
File file = new File (destDir, filename);
File directory = new File(file.getParent());
if (!directory.exists() && !directory.mkdirs()) {
GlobalOptions.err.println
("Could not create directory "
+ directory.getPath() + ", check permissions.");
}
writer = new TabbedPrintWriter
(new BufferedOutputStream(new FileOutputStream(file)),
imports, false);
}
GlobalOptions.err.println(params[i]);
ClassAnalyzer clazzAna = new ClassAnalyzer(clazz, imports);
clazzAna.dumpJavaFile(writer);
if (destZip != null) {
writer.flush();
destZip.closeEntry();
} else if (destDir != null)
writer.close();
/* Now is a good time to clean up */
System.gc();
} catch (IOException ex) {
GlobalOptions.err.println
("Can't write source of "+params[i]+".");
GlobalOptions.err.println("Check the permissions.");
ex.printStackTrace(GlobalOptions.err);
}
}
if (destZip != null) {
try {
destZip.close();
} catch (IOException ex) {
GlobalOptions.err.println("Can't close Zipfile");
ex.printStackTrace(GlobalOptions.err);
}
}
}
}

@ -1,7 +1,7 @@
/* GlobalOptions Copyright (C) 1999-2002 Jochen Hoenicke.
/* GlobalOptions Copyright (C) 1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
@ -10,14 +10,14 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; see the file COPYING.LESSER. If not, write to
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package net.sf.jode;
package jode;
import java.io.PrintWriter;
import java.util.StringTokenizer;
@ -25,8 +25,9 @@ public class GlobalOptions {
public final static String version = "@VERSION@";
public final static String email = "jochen@gnu.org";
public final static String copyright =
"Jode (c) 1998-2004 Jochen Hoenicke <"+email+">";
public final static String URL = "http://jode.sourceforge.net/";
"Jode (c) 1998,1999 Jochen Hoenicke <"+email+">";
public final static String URL =
"http://www.informatik.uni-oldenburg.de/~delwi/jode/jode.html";
public static PrintWriter err = new PrintWriter(System.err, true);
public static int verboseLevel = 0;
@ -80,13 +81,12 @@ public class GlobalOptions {
/**
* Parse the argument given to the debugging flag.
* @exception IllegalArgumentException
* if a problem occured while parsing the argument.
* @return true, if the argument parsed without problems.
*/
public static boolean setDebugging(String debuggingString) {
if (debuggingString.length() == 0 || debuggingString.equals("help")) {
usageDebugging();
throw new IllegalArgumentException();
return false;
}
StringTokenizer st = new StringTokenizer(debuggingString, ",");
@ -99,8 +99,8 @@ public class GlobalOptions {
continue next_token;
}
}
throw new IllegalArgumentException("Illegal debugging flag: "
+token);
err.println("Illegal debugging flag: "+token);
return false;
}
return true;
}

@ -0,0 +1,46 @@
/* JodeApplet Copyright (C) 1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package jode;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class JodeApplet extends Applet {
JodeWindow jodeWin = new JodeWindow(this);
///#ifdef AWT10
/// public boolean action(Event e, Object arg) {
/// jodeWin.action(e);
/// return true;
/// }
///#endif
public void init() {
String cp = getParameter("classpath");
if (cp != null)
jodeWin.setClasspath(cp);
String cls = getParameter("class");
if (cls != null)
jodeWin.setClass(cls);
setFont(new Font("dialog", Font.PLAIN, 10));
}
}

@ -1,7 +1,7 @@
/* Window Copyright (C) 1999-2002 Jochen Hoenicke.
/* JodeWindow Copyright (C) 1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
@ -10,22 +10,25 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; see the file COPYING.LESSER. If not, write to
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package net.sf.jode.decompiler;
package jode;
import java.applet.*;
import java.awt.*;
///#ifndef AWT10
import java.awt.event.*;
///#endif
import java.io.*;
import net.sf.jode.GlobalOptions;
import jode.bytecode.ClassInfo;
import jode.bytecode.SearchPath;
import jode.decompiler.*;
public class Window
public class JodeWindow
implements Runnable
///#ifndef AWT10
, ActionListener
@ -36,29 +39,24 @@ public class Window
TextArea sourcecodeArea, errorArea;
Checkbox verboseCheck, prettyCheck;
Button startButton, saveButton;
String lastClassName, lastClassPath;
String lastClassName;
Frame frame;
PrintWriter errStream;
Decompiler decompiler = new Decompiler();
Thread decompileThread;
public Window(Container window) {
public JodeWindow(Container window) {
buildComponents(window);
}
private void buildComponents(Container window) {
if (window instanceof Frame)
frame = (Frame) window;
window.setFont(new Font("dialog", Font.PLAIN, 10));
classpathField = new TextField(50);
classField = new TextField(50);
sourcecodeArea = new TextArea(20, 80);
errorArea = new TextArea(3, 80);
verboseCheck = new Checkbox("verbose", true);
prettyCheck = new Checkbox("pretty", true);
verboseCheck = new Checkbox("verbose", false);
prettyCheck = new Checkbox("pretty", false);
startButton = new Button("start");
saveButton = new Button("save");
///#ifdef AWT10
@ -146,11 +144,10 @@ public class Window
startButton.addActionListener(this);
saveButton.addActionListener(this);
///#endif
errStream = new PrintWriter(new AreaWriter(errorArea));
decompiler.setErr(errStream);
GlobalOptions.err = new PrintWriter(new AreaWriter(errorArea));
}
public void setClassPath(String cp) {
public void setClasspath(String cp) {
classpathField.setText(cp);
}
public void setClass(String cls) {
@ -158,7 +155,7 @@ public class Window
}
///#ifdef AWT10
/// public synchronized void action(Event e, Object target) {
/// public synchronized void action(Object target) {
///#else
public synchronized void actionPerformed(ActionEvent e) {
Object target = e.getSource();
@ -181,7 +178,7 @@ public class Window
FileDialog.SAVE);
fd.setFile(lastClassName.substring
(lastClassName.lastIndexOf('.')+1).concat(".java"));
fd.setVisible(true);
fd.show();
String fileName = fd.getFile();
if (fileName == null)
return;
@ -192,14 +189,14 @@ public class Window
out.close();
} catch (IOException ex) {
errorArea.setText("");
errStream.println("Couldn't write to file "
GlobalOptions.err.println("Couldn't write to file "
+ fileName + ": ");
ex.printStackTrace(errStream);
ex.printStackTrace(GlobalOptions.err);
} catch (SecurityException ex) {
errorArea.setText("");
errStream.println("Couldn't write to file "
GlobalOptions.err.println("Couldn't write to file "
+ fileName + ": ");
ex.printStackTrace(errStream);
ex.printStackTrace(GlobalOptions.err);
}
}
}
@ -232,8 +229,11 @@ public class Window
}
public void run() {
decompiler.setOption("verbose", verboseCheck.getState() ? "1" : "0");
decompiler.setOption("pretty", prettyCheck.getState() ? "1" : "0");
GlobalOptions.verboseLevel = verboseCheck.getState() ? 1 : 0;
if (prettyCheck.getState())
Decompiler.options |= Decompiler.OPTION_PRETTY;
else
Decompiler.options &= ~Decompiler.OPTION_PRETTY;
errorArea.setText("");
///#ifdef AWT10
/// saveButton.disable();
@ -242,25 +242,26 @@ public class Window
///#endif
lastClassName = classField.getText();
String newClassPath = classpathField.getText();
if (!newClassPath.equals(lastClassPath)) {
decompiler.setClassPath(newClassPath);
lastClassPath = newClassPath;
}
ClassInfo.setClassPath(classpathField.getText());
ImportHandler imports = new ImportHandler();
try {
Writer writer
= new BufferedWriter(new AreaWriter(sourcecodeArea), 512);
ClassInfo clazz;
try {
decompiler.decompile(lastClassName, writer, null);
clazz = ClassInfo.forName(lastClassName);
} catch (IllegalArgumentException ex) {
sourcecodeArea.setText
("`"+lastClassName+"' is not a class name.\n"
("`"+lastClassName+"' is not a class name\n"
+"You have to give a full qualified classname "
+"with '.' as package delimiter \n"
+"and without .class ending.");
+"and without .class ending");
return;
}
TabbedPrintWriter writer =
new TabbedPrintWriter(new AreaWriter(sourcecodeArea), imports);
ClassAnalyzer clazzAna = new ClassAnalyzer(null, clazz, imports);
clazzAna.dumpJavaFile(writer);
///#ifdef AWT10
/// saveButton.enable();
///#else
@ -284,12 +285,12 @@ public class Window
public static void main(String argv[]) {
Frame frame = new Frame(GlobalOptions.copyright);
Window win = new Window(frame);
JodeWindow win = new JodeWindow(frame);
String cp = System.getProperty("java.class.path");
if (cp != null)
win.setClassPath(cp.replace(File.pathSeparatorChar,
Decompiler.altPathSeparatorChar));
win.setClasspath(cp.replace(File.pathSeparatorChar,
SearchPath.pathSeparatorChar));
String cls = win.getClass().getName();
win.setClass(cls);
@ -301,6 +302,6 @@ public class Window
});
///#endif
frame.pack();
frame.setVisible(true);
frame.show();
}
}

@ -0,0 +1,54 @@
## Input file for automake to generate the Makefile.in used by configure
SUBDIRS = bytecode type util jvm expr flow decompiler obfuscator @SWINGUI@
JAR = @JAR@
JAVAC = @JAVAC@
JIKES = @JIKES@
CLASSPATH = @CLASSPATH@
CLASSLIB = @CLASSLIB@
BUILD_CLASSPATH = $(top_srcdir):$(top_builddir):.:$(CLASSPATH):$(CLASSLIB)
VPATH=$(srcdir):$(top_srcdir):$(top_builddir)
MY_JAVA_FILES = \
AssertError.java \
Decompiler.java \
GlobalOptions.java \
JodeApplet.java \
JodeWindow.java
noinst_DATA = $(MY_JAVA_FILES:.java=.class)
EXTRA_DIST = $(MY_JAVA_FILES)
JARFILE = jode-@VERSION@.jar
data_DATA = $(JARFILE)
if HAVE_JIKES
@QUOTE@-include $(top_builddir)/jode/.java.deps
%.class: %.java
$(JIKES) -classpath $(BUILD_CLASSPATH):$(CLASSLIB) +M=$(top_builddir)/jode/.java.deps -d $(top_builddir) $<
else
%.class: %.java
$(JAVAC) -classpath $(BUILD_CLASSPATH):$(CLASSLIB) -depend -d $(top_builddir) $<
endif
clean-local:
@rm -f *.class
@rm -f $(JARFILE) .java.deps
$(JARFILE): $(noinst_DATA)
CLASSPATH=$(top_builddir):$(CLASSPATH) $(JAVA) -mx80m \
jode.obfuscator.Main --dest $(JARFILE) \
--revtable rename.table \
--rename=none --breakserial --strip=unreach -v -v \
--preserve 'jode.Decompiler.main.*' \
--preserve 'jode.JodeApplet.<init>.*' \
--preserve 'jode.JodeWindow.main.*' \
--preserve 'jode.obfuscator.Main.main.*' \
--preserve 'jode.swingui.Main.main.*' jode

@ -0,0 +1,2 @@
Makefile
Makefile.in

@ -0,0 +1,201 @@
/* BinaryInfo Copyright (C) 1998-1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package jode.bytecode;
import java.io.*;
import jode.util.SimpleMap;
///#ifdef JDK12
///import java.util.Map;
///import java.util.Iterator;
///#else
import jode.util.Map;
import jode.util.Iterator;
///#endif
/**
*
* @author Jochen Hoenicke
*/
public class BinaryInfo {
public static final int HIERARCHY = 0x01;
public static final int FIELDS = 0x02;
public static final int METHODS = 0x04;
public static final int CONSTANTS = 0x08;
public static final int ALL_ATTRIBUTES = 0x10;
public static final int INNERCLASSES = 0x20;
public static final int OUTERCLASSES = 0x40;
public static final int FULLINFO = 0xff;
private Map unknownAttributes = new SimpleMap();
protected void skipAttributes(DataInputStream input) throws IOException {
int count = input.readUnsignedShort();
for (int i=0; i< count; i++) {
input.readUnsignedShort(); // the name index
long length = input.readInt();
while (length > 0) {
long skipped = input.skip(length);
if (skipped == 0)
throw new EOFException("Can't skip. EOF?");
length -= skipped;
}
}
}
protected int getKnownAttributeCount() {
return 0;
}
protected void readAttribute(String name, int length,
ConstantPool constantPool,
DataInputStream input,
int howMuch) throws IOException {
byte[] data = new byte[length];
input.readFully(data);
if ((howMuch & ALL_ATTRIBUTES) != 0)
unknownAttributes.put(name, data);
}
static class ConstrainedInputStream extends FilterInputStream {
int length;
public ConstrainedInputStream(int attrLength, InputStream input) {
super(input);
length = attrLength;
}
public int read() throws IOException {
if (length > 0) {
int data = super.read();
length--;
return data;
}
throw new EOFException();
}
public int read(byte[] b, int off, int len) throws IOException {
if (length < len) {
len = length;
}
if (len == 0)
return -1;
int count = super.read(b, off, len);
length -= count;
return count;
}
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
public long skip(long count) throws IOException {
if (length < count) {
count = length;
}
count = super.skip(count);
length -= (int) count;
return count;
}
public void skipRemaining() throws IOException {
while (length > 0) {
int skipped = (int) skip(length);
if (skipped == 0)
throw new EOFException();
length -= skipped;
}
}
}
protected void readAttributes(ConstantPool constantPool,
DataInputStream input,
int howMuch) throws IOException {
int count = input.readUnsignedShort();
unknownAttributes.clear();
for (int i=0; i< count; i++) {
String attrName =
constantPool.getUTF8(input.readUnsignedShort());
final int attrLength = input.readInt();
ConstrainedInputStream constrInput =
new ConstrainedInputStream(attrLength, input);
readAttribute(attrName, attrLength,
constantPool, new DataInputStream(constrInput),
howMuch);
constrInput.skipRemaining();
}
}
protected void prepareAttributes(GrowableConstantPool gcp) {
Iterator i = unknownAttributes.keySet().iterator();
while (i.hasNext())
gcp.putUTF8((String) i.next());
}
protected void writeKnownAttributes
(GrowableConstantPool constantPool,
DataOutputStream output) throws IOException {
}
protected void writeAttributes
(GrowableConstantPool constantPool,
DataOutputStream output) throws IOException {
int count = unknownAttributes.size() + getKnownAttributeCount();
output.writeShort(count);
writeKnownAttributes(constantPool, output);
Iterator i = unknownAttributes.entrySet().iterator();
while (i.hasNext()) {
Map.Entry e = (Map.Entry) i.next();
String name = (String) e.getKey();
byte[] data = (byte[]) e.getValue();
output.writeShort(constantPool.putUTF8(name));
output.writeInt(data.length);
output.write(data);
}
}
public int getAttributeSize() {
int size = 2; /* attribute count */
Iterator i = unknownAttributes.values().iterator();
while (i.hasNext())
size += 2 + 4 + ((byte[]) i.next()).length;
return size;
}
public byte[] findAttribute(String name) {
return (byte[]) unknownAttributes.get(name);
}
public Iterator getAttributes() {
return unknownAttributes.values().iterator();
}
public void setAttribute(String name, byte[] content) {
unknownAttributes.put(name, content);
}
public byte[] removeAttribute(String name) {
return (byte[]) unknownAttributes.remove(name);
}
public void removeAllAttributes() {
unknownAttributes.clear();
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,33 @@
/* ClassFormatException Copyright (C) 1998-1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package jode.bytecode;
/**
* This exception is thrown, if the class file has an unknown format.
* @author Jochen Hoenicke
*/
public class ClassFormatException extends java.io.IOException{
public ClassFormatException(String detail) {
super(detail);
}
public ClassFormatException() {
super();
}
}

@ -0,0 +1,780 @@
/* ClassInfo Copyright (C) 1998-1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package jode.bytecode;
import jode.GlobalOptions;
import jode.type.Type;
import java.io.*;
import java.util.*;
///#ifdef JDK12
///import java.lang.ref.WeakReference;
///import java.lang.ref.ReferenceQueue;
///#endif
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* This class does represent a class similar to java.lang.Class. You
* can get the super class and the interfaces.
*
* The main difference to java.lang.Class is, that the objects are builded
* from a stream containing the .class file, and that it uses the
* <code>Type</code> to represent types instead of Class itself.
*
* @author Jochen Hoenicke
*/
public class ClassInfo extends BinaryInfo {
private static SearchPath classpath;
///#ifdef JDK12
/// private static final Map classes = new HashMap();
/// private static final ReferenceQueue queue = new ReferenceQueue();
///#else
private static final Hashtable classes = new Hashtable();
///#endif
private int status = 0;
private boolean modified = false;
private int modifiers = -1;
private String name;
private ClassInfo superclass;
private ClassInfo[] interfaces;
private FieldInfo[] fields;
private MethodInfo[] methods;
private InnerClassInfo[] outerClasses;
private InnerClassInfo[] innerClasses;
private InnerClassInfo[] extraClasses;
private String sourceFile;
public final static ClassInfo javaLangObject = forName("java.lang.Object");
public static void setClassPath(String path) {
classpath = new SearchPath(path);
///#ifdef JDK12
/// java.lang.ref.Reference died;
/// while ((died = queue.poll()) != null) {
/// classes.values().remove(died);
/// }
/// Iterator i = classes.values().iterator();
/// while (i.hasNext()) {
/// ClassInfo ci = (ClassInfo) ((WeakReference)i.next()).get();
/// if (ci == null) {
/// i.remove();
/// continue;
/// }
///#else
Enumeration enum = classes.elements();
while (enum.hasMoreElements()) {
ClassInfo ci = (ClassInfo) enum.nextElement();
///#endif
ci.status = 0;
ci.superclass = null;
ci.fields = null;
ci.interfaces = null;
ci.methods = null;
ci.removeAllAttributes();
}
}
public static boolean exists(String name) {
return classpath.exists(name.replace('.', '/') + ".class");
}
public static boolean isPackage(String name) {
return classpath.isDirectory(name.replace('.', '/'));
}
public static Enumeration getClassesAndPackages(final String packageName) {
final Enumeration enum =
classpath.listFiles(packageName.replace('.','/'));
return new Enumeration() {
public boolean hasMoreElements() {
return enum.hasMoreElements();
}
public Object nextElement() {
String name = (String) enum.nextElement();
if (!name.endsWith(".class"))
// This is a package
return name;
return name.substring(0, name.length()-6);
}
};
}
public static ClassInfo forName(String name) {
if (name == null
|| name.indexOf(';') != -1
|| name.indexOf('[') != -1
|| name.indexOf('/') != -1)
throw new IllegalArgumentException("Illegal class name: "+name);
///#ifdef JDK12
/// java.lang.ref.Reference died;
/// while ((died = queue.poll()) != null) {
/// classes.values().remove(died);
/// }
/// WeakReference ref = (WeakReference) classes.get(name);
/// ClassInfo clazz = (ref == null) ? null : (ClassInfo) ref.get();
///#else
ClassInfo clazz = (ClassInfo) classes.get(name);
///#endif
if (clazz == null) {
clazz = new ClassInfo(name);
///#ifdef JDK12
/// classes.put(name, new WeakReference(clazz, queue));
///#else
classes.put(name, clazz);
///#endif
}
return clazz;
}
private ClassInfo(String name) {
this.name = name;
}
protected void readAttribute(String name, int length,
ConstantPool cp,
DataInputStream input,
int howMuch) throws IOException {
if ((howMuch & ALL_ATTRIBUTES) != 0 && name.equals("SourceFile")) {
if (length != 2)
throw new ClassFormatException("SourceFile attribute"
+ " has wrong length");
sourceFile = cp.getUTF8(input.readUnsignedShort());
} else if ((howMuch & (OUTERCLASSES | INNERCLASSES)) != 0
&& name.equals("InnerClasses")) {
int count = input.readUnsignedShort();
int innerCount = 0, outerCount = 0, extraCount = 0;
InnerClassInfo[] innerClassInfo = new InnerClassInfo[count];
for (int i=0; i< count; i++) {
int innerIndex = input.readUnsignedShort();
int outerIndex = input.readUnsignedShort();
int nameIndex = input.readUnsignedShort();
String inner = cp.getClassName(innerIndex);
String outer =
outerIndex != 0 ? cp.getClassName(outerIndex) : null;
String innername =
nameIndex != 0 ? cp.getUTF8(nameIndex) : null;
int access = input.readUnsignedShort();
if (innername != null && innername.length() == 0)
innername = null;
InnerClassInfo ici = new InnerClassInfo
(inner, outer, innername, access);
if (outer != null && outer.equals(getName())
&& innername != null)
innerClassInfo[innerCount++] = ici;
else
innerClassInfo[count - (++extraCount)] = ici;
}
{
String lastOuterName = getName();
for (int i = count - extraCount; i < count; i++) {
InnerClassInfo ici = innerClassInfo[i];
if (ici.inner.equals(lastOuterName)) {
for (int j = i; j > count - extraCount; j--)
innerClassInfo[j] = innerClassInfo[j-1];
innerClassInfo[count-extraCount] = ici;
extraCount--;
outerCount++;
lastOuterName = ici.outer;
}
}
}
if (innerCount > 0) {
innerClasses = new InnerClassInfo[innerCount];
System.arraycopy(innerClassInfo, 0,
innerClasses, 0, innerCount);
} else
innerClasses = null;
if (outerCount > 0) {
outerClasses = new InnerClassInfo[outerCount];
System.arraycopy(innerClassInfo, innerCount,
outerClasses, 0, outerCount);
} else
outerClasses = null;
if (extraCount > 0) {
extraClasses = new InnerClassInfo[extraCount];
System.arraycopy(innerClassInfo, innerCount + outerCount,
extraClasses, 0, extraCount);
} else
extraClasses = null;
if (length != 2 + 8 * count)
throw new ClassFormatException
("InnerClasses attribute has wrong length");
} else
super.readAttribute(name, length, cp, input, howMuch);
}
public void read(DataInputStream input, int howMuch) throws IOException {
/* Since we have to read the whole class anyway, we load all
* info, that we may need later and that does not take much memory.
*/
howMuch |= FIELDS | METHODS | HIERARCHY | INNERCLASSES | OUTERCLASSES;
howMuch &= ~status;
/* header */
if (input.readInt() != 0xcafebabe)
throw new ClassFormatException("Wrong magic");
if (input.readUnsignedShort() > 3)
throw new ClassFormatException("Wrong minor");
if (input.readUnsignedShort() != 45)
throw new ClassFormatException("Wrong major");
/* constant pool */
ConstantPool cpool = new ConstantPool();
cpool.read(input);
/* always read modifiers, name, super, ifaces */
{
modifiers = input.readUnsignedShort();
String className = cpool.getClassName(input.readUnsignedShort());
if (!name.equals(className))
throw new ClassFormatException("wrong name " + className);
String superName = cpool.getClassName(input.readUnsignedShort());
superclass = superName != null ? ClassInfo.forName(superName) : null;
int count = input.readUnsignedShort();
interfaces = new ClassInfo[count];
for (int i=0; i< count; i++) {
interfaces[i] = ClassInfo.forName
(cpool.getClassName(input.readUnsignedShort()));
}
status |= HIERARCHY;
}
/* fields */
if ((howMuch & (FIELDS | ALL_ATTRIBUTES)) != 0) {
int count = input.readUnsignedShort();
if ((howMuch & FIELDS) != 0)
fields = new FieldInfo[count];
for (int i=0; i< count; i++) {
if ((howMuch & FIELDS) != 0)
fields[i] = new FieldInfo(this);
fields[i].read(cpool, input, howMuch);
}
} else {
byte[] skipBuf = new byte[6];
int count = input.readUnsignedShort();
for (int i=0; i< count; i++) {
input.readFully(skipBuf); // modifier, name, type
skipAttributes(input);
}
}
/* methods */
if ((howMuch & (METHODS | ALL_ATTRIBUTES)) != 0) {
int count = input.readUnsignedShort();
if ((howMuch & METHODS) != 0)
methods = new MethodInfo[count];
for (int i=0; i< count; i++) {
if ((howMuch & METHODS) != 0)
methods[i] = new MethodInfo(this);
methods[i].read(cpool, input, howMuch);
}
} else {
byte[] skipBuf = new byte[6];
int count = input.readUnsignedShort();
for (int i=0; i< count; i++) {
input.readFully(skipBuf); // modifier, name, type
skipAttributes(input);
}
}
/* attributes */
readAttributes(cpool, input, howMuch);
status |= howMuch;
}
public void reserveSmallConstants(GrowableConstantPool gcp) {
for (int i=0; i < fields.length; i++)
fields[i].reserveSmallConstants(gcp);
for (int i=0; i < methods.length; i++)
methods[i].reserveSmallConstants(gcp);
}
public void prepareWriting(GrowableConstantPool gcp) {
gcp.putClassName(name);
gcp.putClassName(superclass.getName());
for (int i=0; i < interfaces.length; i++)
gcp.putClassName(interfaces[i].getName());
for (int i=0; i < fields.length; i++)
fields[i].prepareWriting(gcp);
for (int i=0; i < methods.length; i++)
methods[i].prepareWriting(gcp);
if (sourceFile != null) {
gcp.putUTF8("SourceFile");
gcp.putUTF8(sourceFile);
}
if (outerClasses != null || innerClasses != null
|| extraClasses != null) {
gcp.putUTF8("InnerClasses");
int outerCount = outerClasses != null ? outerClasses.length : 0;
for (int i=outerCount; i-- > 0;) {
gcp.putClassName(outerClasses[i].inner);
if (outerClasses[i].outer != null)
gcp.putClassName(outerClasses[i].outer);
if (outerClasses[i].name != null)
gcp.putUTF8(outerClasses[i].name);
}
int innerCount = innerClasses != null ? innerClasses.length : 0;
for (int i=0; i< innerCount; i++) {
gcp.putClassName(innerClasses[i].inner);
if (innerClasses[i].outer != null)
gcp.putClassName(innerClasses[i].outer);
if (innerClasses[i].name != null)
gcp.putUTF8(innerClasses[i].name);
}
int extraCount = extraClasses != null ? extraClasses.length : 0;
for (int i=0; i< extraCount; i++) {
gcp.putClassName(extraClasses[i].inner);
if (extraClasses[i].outer != null)
gcp.putClassName(extraClasses[i].outer);
if (extraClasses[i].name != null)
gcp.putUTF8(extraClasses[i].name);
}
}
prepareAttributes(gcp);
}
protected int getKnownAttributeCount() {
int count = 0;
if (sourceFile != null)
count++;
if (innerClasses != null || outerClasses != null
|| extraClasses != null)
count++;
return count;
}
public void writeKnownAttributes(GrowableConstantPool gcp,
DataOutputStream output)
throws IOException {
if (sourceFile != null) {
output.writeShort(gcp.putUTF8("SourceFile"));
output.writeInt(2);
output.writeShort(gcp.putUTF8(sourceFile));
}
if (outerClasses != null || innerClasses != null
|| extraClasses != null) {
output.writeShort(gcp.putUTF8("InnerClasses"));
int outerCount = (outerClasses != null) ? outerClasses.length : 0;
int innerCount = (innerClasses != null) ? innerClasses.length : 0;
int extraCount = (extraClasses != null) ? extraClasses.length : 0;
int count = outerCount + innerCount + extraCount;
output.writeInt(2 + count * 8);
output.writeShort(count);
for (int i=outerCount; i-- > 0; ) {
output.writeShort(gcp.putClassName(outerClasses[i].inner));
output.writeShort(outerClasses[i].outer != null ?
gcp.putClassName(outerClasses[i].outer) : 0);
output.writeShort(outerClasses[i].name != null ?
gcp.putUTF8(outerClasses[i].name) : 0);
output.writeShort(outerClasses[i].modifiers);
}
for (int i=0; i< innerCount; i++) {
output.writeShort(gcp.putClassName(innerClasses[i].inner));
output.writeShort(innerClasses[i].outer != null ?
gcp.putClassName(innerClasses[i].outer) : 0);
output.writeShort(innerClasses[i].name != null ?
gcp.putUTF8(innerClasses[i].name) : 0);
output.writeShort(innerClasses[i].modifiers);
}
for (int i=0; i< extraCount; i++) {
output.writeShort(gcp.putClassName(extraClasses[i].inner));
output.writeShort(extraClasses[i].outer != null ?
gcp.putClassName(extraClasses[i].outer) : 0);
output.writeShort(extraClasses[i].name != null ?
gcp.putUTF8(extraClasses[i].name) : 0);
output.writeShort(extraClasses[i].modifiers);
}
}
}
public void write(DataOutputStream out) throws IOException {
GrowableConstantPool gcp = new GrowableConstantPool();
reserveSmallConstants(gcp);
prepareWriting(gcp);
out.writeInt(0xcafebabe);
out.writeShort(3);
out.writeShort(45);
gcp.write(out);
out.writeShort(modifiers);
out.writeShort(gcp.putClassName(name));
out.writeShort(gcp.putClassName(superclass.getName()));
out.writeShort(interfaces.length);
for (int i=0; i < interfaces.length; i++)
out.writeShort(gcp.putClassName(interfaces[i].getName()));
out.writeShort(fields.length);
for (int i=0; i < fields.length; i++)
fields[i].write(gcp, out);
out.writeShort(methods.length);
for (int i=0; i < methods.length; i++)
methods[i].write(gcp, out);
writeAttributes(gcp, out);
}
public void loadInfoReflection(Class clazz, int howMuch)
throws SecurityException {
if ((howMuch & HIERARCHY) != 0) {
modifiers = clazz.getModifiers();
if (clazz.getSuperclass() == null)
superclass = null;
else
superclass = ClassInfo.forName
(clazz.getSuperclass().getName());
Class[] ifaces = clazz.getInterfaces();
interfaces = new ClassInfo[ifaces.length];
for (int i=0; i<ifaces.length; i++)
interfaces[i] = ClassInfo.forName(ifaces[i].getName());
status |= HIERARCHY;
}
if ((howMuch & FIELDS) != 0 && fields == null) {
Field[] fs;
try {
fs = clazz.getDeclaredFields();
} catch (SecurityException ex) {
fs = clazz.getFields();
GlobalOptions.err.println
("Could only get public fields of class "
+ name + ".");
}
fields = new FieldInfo[fs.length];
for (int i = fs.length; --i >= 0; ) {
String type = Type.getSignature(fs[i].getType());
fields[i] = new FieldInfo
(this, fs[i].getName(), type, fs[i].getModifiers());
}
}
if ((howMuch & METHODS) != 0 && methods == null) {
Method[] ms;
try {
ms = clazz.getDeclaredMethods();
} catch (SecurityException ex) {
ms = clazz.getMethods();
GlobalOptions.err.println
("Could only get public methods of class "
+ name + ".");
}
methods = new MethodInfo[ms.length];
for (int i = ms.length; --i >= 0; ) {
String type = Type.getSignature
(ms[i].getParameterTypes(), ms[i].getReturnType());
methods[i] = new MethodInfo
(this, ms[i].getName(), type, ms[i].getModifiers());
}
}
if ((howMuch & INNERCLASSES) != 0 && innerClasses == null) {
Class[] is;
try {
is = clazz.getDeclaredClasses();
} catch (SecurityException ex) {
is = clazz.getClasses();
GlobalOptions.err.println
("Could only get public methods of class "
+ name + ".");
}
if (is.length > 0) {
innerClasses = new InnerClassInfo[is.length];
for (int i = is.length; --i >= 0; ) {
String inner = is[i].getName();
int dollar = inner.lastIndexOf('$');
String name = inner.substring(dollar+1);
innerClasses[i] = new InnerClassInfo
(inner, getName(), name, is[i].getModifiers());
}
}
}
if ((howMuch & OUTERCLASSES) != 0 && outerClasses == null) {
int count = 0;
Class declarer = clazz.getDeclaringClass();
while (declarer != null) {
count++;
declarer = declarer.getDeclaringClass();
}
if (count > 0) {
outerClasses = new InnerClassInfo[count];
Class current = clazz;
for (int i = 0; i < count; i++) {
declarer = current.getDeclaringClass();
String name = current.getName();
int dollar = name.lastIndexOf('$');
outerClasses[i] = new InnerClassInfo
(name, declarer.getName(),
name.substring(dollar+1), current.getModifiers());
current = declarer;
}
}
}
status |= howMuch;
}
public void loadInfo(int howMuch) {
if ((status & howMuch) == howMuch)
return;
if (modified) {
System.err.println("Allocating info 0x"
+ Integer.toHexString(howMuch)
+ " (status 0x" + Integer.toHexString(status)
+ ") in class " + this);
Thread.dumpStack();
return;
}
try {
DataInputStream input =
new DataInputStream(classpath.getFile(name.replace('.', '/')
+ ".class"));
read(input, howMuch);
} catch (IOException ex) {
String message = ex.getMessage();
if ((howMuch & ~(FIELDS|METHODS|HIERARCHY
|INNERCLASSES|OUTERCLASSES)) != 0) {
GlobalOptions.err.println
("Can't read class " + name + ".");
ex.printStackTrace(GlobalOptions.err);
throw new NoClassDefFoundError(name);
}
// Try getting the info through the reflection interface
// instead.
Class clazz = null;
try {
clazz = Class.forName(name);
} catch (ClassNotFoundException ex2) {
} catch (NoClassDefFoundError ex2) {
}
try {
if (clazz != null) {
loadInfoReflection(clazz, howMuch);
return;
}
} catch (SecurityException ex2) {
GlobalOptions.err.println
(ex2+" while collecting info about class " + name + ".");
}
// Give a warning and ``guess'' the hierarchie, methods etc.
GlobalOptions.err.println
("Can't read class " + name + ", types may be incorrect. ("
+ ex.getClass().getName()
+ (message != null ? ": " + message : "") + ")");
if ((howMuch & HIERARCHY) != 0) {
modifiers = Modifier.PUBLIC;
if (name.equals("java.lang.Object"))
superclass = null;
else
superclass = javaLangObject;
interfaces = new ClassInfo[0];
}
if ((howMuch & METHODS) != 0)
methods = new MethodInfo[0];
if ((howMuch & FIELDS) != 0)
fields = new FieldInfo[0];
status |= howMuch;
}
}
public String getName() {
return name;
}
public String getJavaName() {
/* Don't load attributes for class names not containing a
* dollar sign.
*/
if (name.indexOf('$') == -1)
return getName();
if (getOuterClasses() != null) {
int last = outerClasses.length-1;
StringBuffer sb =
new StringBuffer(outerClasses[last].outer != null
? outerClasses[last].outer : "METHOD");
for (int i=last; i >= 0; i--)
sb.append(".").append(outerClasses[i].name != null
? outerClasses[i].name : "ANONYMOUS");
return sb.toString();
}
return getName();
}
public ClassInfo getSuperclass() {
if ((status & HIERARCHY) == 0)
loadInfo(HIERARCHY);
return superclass;
}
public ClassInfo[] getInterfaces() {
if ((status & HIERARCHY) == 0)
loadInfo(HIERARCHY);
return interfaces;
}
public int getModifiers() {
if ((status & HIERARCHY) == 0)
loadInfo(HIERARCHY);
return modifiers;
}
public boolean isInterface() {
return Modifier.isInterface(getModifiers());
}
public FieldInfo findField(String name, String typeSig) {
if ((status & FIELDS) == 0)
loadInfo(FIELDS);
for (int i=0; i< fields.length; i++)
if (fields[i].getName().equals(name)
&& fields[i].getType().equals(typeSig))
return fields[i];
return null;
}
public MethodInfo findMethod(String name, String typeSig) {
if ((status & METHODS) == 0)
loadInfo(METHODS);
for (int i=0; i< methods.length; i++)
if (methods[i].getName().equals(name)
&& methods[i].getType().equals(typeSig))
return methods[i];
return null;
}
public MethodInfo[] getMethods() {
if ((status & METHODS) == 0)
loadInfo(METHODS);
return methods;
}
public FieldInfo[] getFields() {
if ((status & FIELDS) == 0)
loadInfo(FIELDS);
return fields;
}
public InnerClassInfo[] getOuterClasses() {
if ((status & OUTERCLASSES) == 0)
loadInfo(OUTERCLASSES);
return outerClasses;
}
public InnerClassInfo[] getInnerClasses() {
if ((status & INNERCLASSES) == 0)
loadInfo(INNERCLASSES);
return innerClasses;
}
public InnerClassInfo[] getExtraClasses() {
if ((status & INNERCLASSES) == 0)
loadInfo(INNERCLASSES);
return extraClasses;
}
public String getSourceFile() {
return sourceFile;
}
public void setName(String newName) {
name = newName;
modified = true;
}
public void setSuperclass(ClassInfo newSuper) {
superclass = newSuper;
modified = true;
}
public void setInterfaces(ClassInfo[] newIfaces) {
interfaces = newIfaces;
modified = true;
}
public void setModifiers(int newModifiers) {
modifiers = newModifiers;
modified = true;
}
public void setMethods(MethodInfo[] mi) {
methods = mi;
modified = true;
}
public void setFields(FieldInfo[] fi) {
fields = fi;
modified = true;
}
public void setOuterClasses(InnerClassInfo[] oc) {
outerClasses = oc;
modified = true;
}
public void setInnerClasses(InnerClassInfo[] ic) {
innerClasses = ic;
modified = true;
}
public void setExtraClasses(InnerClassInfo[] ec) {
extraClasses = ec;
modified = true;
}
public void setSourceFile(String newSource) {
sourceFile = newSource;
modified = true;
}
public boolean superClassOf(ClassInfo son) {
while (son != this && son != null) {
son = son.getSuperclass();
}
return son == this;
}
public boolean implementedBy(ClassInfo clazz) {
while (clazz != this && clazz != null) {
ClassInfo[] ifaces = clazz.getInterfaces();
for (int i=0; i< ifaces.length; i++) {
if (implementedBy(ifaces[i]))
return true;
}
clazz = clazz.getSuperclass();
}
return clazz == this;
}
public String toString() {
return name;
}
}

@ -1,7 +1,7 @@
/* ConstantPool Copyright (C) 1998-2002 Jochen Hoenicke.
/* ConstantPool Copyright (C) 1998-1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
@ -10,30 +10,19 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; see the file COPYING.LESSER. If not, write to
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package net.sf.jode.bytecode;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.NoSuchElementException;
///#def COLLECTIONS java.util
import java.util.Iterator;
///#enddef
///#def COLLECTIONEXTRA java.lang
import java.lang.UnsupportedOperationException;
///#enddef
package jode.bytecode;
import java.io.*;
import jode.type.Type;
/**
* This class represent the constant pool. Normally you wont need to
* touch this class, as ClassInfo already does all the hard work. You
* will only need it if you want to add your own custom attributes
* that use the constant pool.
* This class represent the constant pool.
*
* @author Jochen Hoenicke
*/
@ -56,6 +45,76 @@ public class ConstantPool {
Object[] constants;
void checkClassName(String clName) throws ClassFormatException {
boolean start = true;
for (int i=0; i< clName.length(); i++) {
char c = clName.charAt(i);
if (c == '/')
start = true;
else if (start && Character.isJavaIdentifierStart(c))
start = false;
else if ((start && false /*XXX*/)
|| !Character.isJavaIdentifierPart(c))
throw new ClassFormatException("Illegal java class name: "
+ clName);
}
}
void checkTypeSig(String typesig, boolean isMethod)
throws ClassFormatException {
try {
int i = 0;
if (isMethod) {
if (typesig.charAt(i++) != '(')
throw new ClassFormatException
("Type sig doesn't match tag: "+typesig);
while (typesig.charAt(i) != ')') {
while (typesig.charAt(i) == '[') {
i++;
if (i >= typesig.length())
throw new ClassFormatException
("Type sig error: "+typesig);
}
if (typesig.charAt(i) == 'L') {
int end = typesig.indexOf(';', i);
if (end == -1)
throw new ClassFormatException
("Type sig error: "+typesig);
checkClassName(typesig.substring(i+1, end));
i = end;
} else {
if ("ZBSCIJFD".indexOf(typesig.charAt(i)) == -1)
throw new ClassFormatException
("Type sig error: "+typesig);
}
i++;
}
i++;
}
while (typesig.charAt(i) == '[')
i++;
if (typesig.charAt(i) == 'L') {
int end = typesig.indexOf(';', i);
if (i == -1)
throw new ClassFormatException
("Type sig error: "+typesig);
checkClassName(typesig.substring(i+1, end));
i = end;
} else {
if ("ZBSCIJFD".indexOf(typesig.charAt(i)) == -1)
if (!isMethod || typesig.charAt(i) != 'V')
throw new ClassFormatException
("Type sig error: "+typesig);
}
if (i+1 != typesig.length())
throw new ClassFormatException
("Type sig error: "+typesig);
} catch (StringIndexOutOfBoundsException ex) {
throw new ClassFormatException
("Incomplete type sig: "+typesig);
}
}
public ConstantPool () {
}
@ -117,12 +176,16 @@ public class ConstantPool {
}
public String getUTF8(int i) throws ClassFormatException {
if (i == 0)
return null;
if (tags[i] != UTF8)
throw new ClassFormatException("Tag mismatch");
return (String)constants[i];
}
public Reference getRef(int i) throws ClassFormatException {
if (i == 0)
return null;
if (tags[i] != FIELDREF
&& tags[i] != METHODREF && tags[i] != INTERFACEMETHODREF)
throw new ClassFormatException("Tag mismatch");
@ -132,14 +195,7 @@ public class ConstantPool {
if (tags[nameTypeIndex] != NAMEANDTYPE)
throw new ClassFormatException("Tag mismatch");
String type = getUTF8(indices2[nameTypeIndex]);
try {
if (tags[i] == FIELDREF)
TypeSignature.checkTypeSig(type);
else
TypeSignature.checkMethodTypeSig(type);
} catch (IllegalArgumentException ex) {
throw new ClassFormatException(ex.getMessage());
}
checkTypeSig(type, tags[i] != FIELDREF);
String clName = getClassType(classIndex);
constants[i] = Reference.getReference
(clName, getUTF8(indices1[nameTypeIndex]), type);
@ -151,85 +207,40 @@ public class ConstantPool {
if (i == 0)
throw new ClassFormatException("null constant");
switch (tags[i]) {
case INTEGER:
case FLOAT:
case LONG:
case DOUBLE:
case ConstantPool.INTEGER:
case ConstantPool.FLOAT:
case ConstantPool.LONG:
case ConstantPool.DOUBLE:
return constants[i];
case CLASS:
return Reference.getReference(getClassType(i),
"class", "Ljava/lang/Class;");
case STRING:
case ConstantPool.STRING:
return getUTF8(indices1[i]);
}
throw new ClassFormatException("Tag mismatch: "+tags[i]);
}
public String getClassType(int i) throws ClassFormatException {
if (i == 0)
return null;
if (tags[i] != CLASS)
throw new ClassFormatException("Tag mismatch");
String clName = getUTF8(indices1[i]);
if (clName.charAt(0) != '[') {
if (clName.charAt(0) == '[')
checkTypeSig(clName, false);
else {
checkClassName(clName);
clName = ("L"+clName+';').intern();
}
try {
TypeSignature.checkTypeSig(clName);
} catch (IllegalArgumentException ex) {
throw new ClassFormatException(ex.getMessage());
}
return clName;
}
public String getClassName(int i) throws ClassFormatException {
if (i == 0)
return null;
if (tags[i] != CLASS)
throw new ClassFormatException("Tag mismatch");
if (constants[i] == null) {
String clName = getUTF8(indices1[i]);
try {
TypeSignature.checkTypeSig("L"+clName+";");
} catch (IllegalArgumentException ex) {
throw new ClassFormatException(ex.getMessage());
}
constants[i] = clName.replace('/','.').intern();
}
return (String) constants[i];
}
/**
* Iterates through all class entries in the class pool and returns
* their (dot seperated) class name.
*/
public Iterator iterateClassNames() {
return new Iterator()
{
int entry = 1;
public boolean hasNext() {
try {
while (entry < count
&& (tags[entry] != CLASS
|| getUTF8(indices1[entry])
.charAt(0) == '['))
entry++;
} catch (ClassFormatException ex) {
throw new InternalError(ex.getMessage());
}
return entry < count;
}
public Object next() {
if (!hasNext())
throw new NoSuchElementException();
try {
return getClassName(entry++);
} catch (ClassFormatException ex) {
throw new InternalError(ex.getMessage());
}
}
public void remove() {
throw new UnsupportedOperationException();
}
};
String clName = getUTF8(indices1[i]);
checkClassName(clName);
return clName.replace('/','.').intern();
}
public String toString(int i) {
@ -270,7 +281,7 @@ public class ConstantPool {
}
public String toString() {
StringBuffer result = new StringBuffer("ConstantPool[ null");
StringBuffer result = new StringBuffer("[ null");
for (int i=1; i< count; i++) {
result.append(", ").append(i).append(" = ").append(toString(i));
}

@ -0,0 +1,195 @@
/* FieldInfo Copyright (C) 1998-1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package jode.bytecode;
import java.io.*;
import java.lang.reflect.Modifier;
public class FieldInfo extends BinaryInfo {
ClassInfo clazzInfo;
int modifier;
String name;
String typeSig;
Object constant;
boolean syntheticFlag;
boolean deprecatedFlag;
public FieldInfo(ClassInfo ci) {
this.clazzInfo = ci;
}
public FieldInfo(ClassInfo ci, String name, String typeSig, int modifier) {
this.clazzInfo = ci;
this.name = name;
this.typeSig = typeSig;
this.modifier = modifier;
}
protected void readAttribute(String name, int length,
ConstantPool cp,
DataInputStream input,
int howMuch) throws IOException {
if ((howMuch & ALL_ATTRIBUTES) != 0 && name.equals("ConstantValue")) {
if (length != 2)
throw new ClassFormatException("ConstantValue attribute"
+ " has wrong length");
int index = input.readUnsignedShort();
constant = cp.getConstant(index);
} else if (name.equals("Synthetic")) {
syntheticFlag = true;
if (length != 0)
throw new ClassFormatException
("Synthetic attribute has wrong length");
} else if (name.equals("Deprecated")) {
deprecatedFlag = true;
if (length != 0)
throw new ClassFormatException
("Deprecated attribute has wrong length");
} else
super.readAttribute(name, length, cp, input, howMuch);
}
public void read(ConstantPool constantPool,
DataInputStream input, int howMuch) throws IOException {
modifier = input.readUnsignedShort();
name = constantPool.getUTF8(input.readUnsignedShort());
typeSig = constantPool.getUTF8(input.readUnsignedShort());
readAttributes(constantPool, input, howMuch);
}
public void reserveSmallConstants(GrowableConstantPool gcp) {
}
public void prepareWriting(GrowableConstantPool gcp) {
gcp.putUTF8(name);
gcp.putUTF8(typeSig);
if (constant != null) {
gcp.putUTF8("ConstantValue");
if (typeSig.charAt(0) == 'J' || typeSig.charAt(0) == 'D')
gcp.putLongConstant(constant);
else
gcp.putConstant(constant);
}
if (syntheticFlag)
gcp.putUTF8("Synthetic");
if (deprecatedFlag)
gcp.putUTF8("Deprecated");
prepareAttributes(gcp);
}
protected int getKnownAttributeCount() {
int count = 0;
if (constant != null)
count++;
if (syntheticFlag)
count++;
if (deprecatedFlag)
count++;
return count;
}
public void writeKnownAttributes(GrowableConstantPool gcp,
DataOutputStream output)
throws IOException {
if (constant != null) {
output.writeShort(gcp.putUTF8("ConstantValue"));
output.writeInt(2);
int index;
if (typeSig.charAt(0) == 'J'
|| typeSig.charAt(0) == 'D')
index = gcp.putLongConstant(constant);
else
index = gcp.putConstant(constant);
output.writeShort(index);
}
if (syntheticFlag) {
output.writeShort(gcp.putUTF8("Synthetic"));
output.writeInt(0);
}
if (deprecatedFlag) {
output.writeShort(gcp.putUTF8("Deprecated"));
output.writeInt(0);
}
}
public void write(GrowableConstantPool constantPool,
DataOutputStream output) throws IOException {
output.writeShort(modifier);
output.writeShort(constantPool.putUTF8(name));
output.writeShort(constantPool.putUTF8(typeSig));
writeAttributes(constantPool, output);
}
public String getName() {
return name;
}
public String getType() {
return typeSig;
}
public int getModifiers() {
return modifier;
}
public boolean isSynthetic() {
return syntheticFlag;
}
public boolean isDeprecated() {
return deprecatedFlag;
}
public Object getConstant() {
clazzInfo.loadInfo(ALL_ATTRIBUTES);
return constant;
}
public void setName(String newName) {
name = newName;
}
public void setType(String newType) {
typeSig = newType;
}
public void setModifiers(int newModifier) {
modifier = newModifier;
}
public void setSynthetic(boolean flag) {
syntheticFlag = flag;
}
public void setDeprecated(boolean flag) {
deprecatedFlag = flag;
}
public void setConstant(Object newConstant) {
constant = newConstant;
}
public String toString() {
return "Field "+Modifier.toString(modifier)+" "+
typeSig+" "+name;
}
}

@ -0,0 +1,257 @@
/* GrowableConstantPool Copyright (C) 1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package jode.bytecode;
import java.io.*;
import jode.type.Type;
import java.util.Hashtable;
/**
* This class represent a constant pool, where new constants can be added to.
*
* @author Jochen Hoenicke
*/
public class GrowableConstantPool extends ConstantPool {
Hashtable entryToIndex = new Hashtable();
boolean written;
public GrowableConstantPool () {
count = 1;
tags = new int[128];
indices1 = new int[128];
indices2 = new int[128];
constants = new Object[128];
written = false;
}
public final void grow(int wantedSize) {
if (written)
throw new IllegalStateException("adding to written ConstantPool");
if (tags.length < wantedSize) {
int newSize = Math.max(tags.length*2, wantedSize);
int[] tmpints = new int[newSize];
System.arraycopy(tags, 0, tmpints, 0, count);
tags = tmpints;
tmpints = new int[newSize];
System.arraycopy(indices1, 0, tmpints, 0, count);
indices1 = tmpints;
tmpints = new int[newSize];
System.arraycopy(indices2, 0, tmpints, 0, count);
indices2 = tmpints;
Object[] tmpobjs = new Object[newSize];
System.arraycopy(constants, 0, tmpobjs, 0, count);
constants = tmpobjs;
}
}
int putConstant(int tag, Object constant) {
String key = "" + (char)tag + constant;
Integer index = (Integer) entryToIndex.get(key);
if (index != null)
return index.intValue();
int newIndex = count;
grow(count + 1);
tags[newIndex] = tag;
constants[newIndex] = constant;
entryToIndex.put(key, new Integer(newIndex));
count++;
return newIndex;
}
int putLongConstant(int tag, Object constant) {
String key = "" + (char)tag + constant;
Integer index = (Integer) entryToIndex.get(key);
if (index != null)
return index.intValue();
int newIndex = count;
grow(count + 2);
tags[newIndex] = tag;
tags[newIndex+1] = -tag;
constants[newIndex] = constant;
entryToIndex.put(key, new Integer(newIndex));
count += 2;
return newIndex;
}
int putIndexed(String key, int tag, int index1, int index2) {
Integer indexObj = (Integer) entryToIndex.get(key);
if (indexObj != null) {
/* Maybe this was a reserved, but not filled entry */
int index = indexObj.intValue();
indices1[index] = index1;
indices2[index] = index2;
return index;
}
grow(count+1);
tags[count] = tag;
indices1[count] = index1;
indices2[count] = index2;
entryToIndex.put(key, new Integer(count));
return count++;
}
public final int putUTF8(String utf) {
return putConstant(UTF8, utf);
}
public int putClassName(String name) {
name = name.replace('.','/');
return putIndexed(""+(char) CLASS + name,
CLASS, putUTF8(name), 0);
}
public int putClassType(String name) {
if (name.charAt(0) == 'L')
name = name.substring(1, name.length()-1);
return putIndexed(""+(char) CLASS + name,
CLASS, putUTF8(name), 0);
}
public int putRef(int tag, Reference ref) {
String className = ref.getClazz();
String typeSig = ref.getType();
String nameAndType = ref.getName() + "/" + typeSig;
int classIndex = putClassType(className);
int nameIndex = putUTF8(ref.getName());
int typeIndex = putUTF8(typeSig);
int nameTypeIndex = putIndexed("" + (char) NAMEANDTYPE + nameAndType,
NAMEANDTYPE, nameIndex, typeIndex);
return putIndexed("" + (char)tag + className + "/" + nameAndType,
tag, classIndex, nameTypeIndex);
}
/**
* Puts a constant into this constant pool
* @param c the constant, must be of type
* Integer, Long, Float, Double or String
* @return the index into the pool of this constant.
*/
public int putConstant(Object c) {
if (c instanceof String) {
return putIndexed("" + (char) STRING + c,
STRING, putUTF8((String) c), 0);
} else {
int tag;
if (c instanceof Integer)
tag = INTEGER;
else if (c instanceof Float)
tag = FLOAT;
else
throw new IllegalArgumentException
("illegal constant " + c + " of type: " + c.getClass());
return putConstant(tag, c);
}
}
/**
* Puts a constant into this constant pool
* @param c the constant, must be of type
* Integer, Long, Float, Double or String
* @return the index into the pool of this constant.
*/
public int putLongConstant(Object c) {
int tag;
if (c instanceof Long)
tag = LONG;
else if (c instanceof Double)
tag = DOUBLE;
else
throw new IllegalArgumentException
("illegal long constant " + c + " of type: " + c.getClass());
return putLongConstant(tag, c);
}
/**
* Reserve an entry in this constant pool for a constant (for ldc).
* @param c the constant, must be of type
* Integer, Long, Float, Double or String
* @return the reserved index into the pool of this constant.
*/
public int reserveConstant(Object c) {
if (c instanceof String) {
return putIndexed("" + (char)STRING + c,
STRING, -1, 0);
} else {
return putConstant(c);
}
}
/**
* Reserve an entry in this constant pool for a constant (for ldc).
* @param c the constant, must be of type
* Integer, Long, Float, Double or String
* @return the reserved index into the pool of this constant.
*/
public int reserveLongConstant(Object c) {
return putLongConstant(c);
}
public int copyConstant(ConstantPool cp, int index)
throws ClassFormatException {
return putConstant(cp.getConstant(index));
}
public void write(DataOutputStream stream)
throws IOException {
written = true;
stream.writeShort(count);
for (int i=1; i< count; i++) {
int tag = tags[i];
stream.writeByte(tag);
switch (tag) {
case CLASS:
stream.writeShort(indices1[i]);
break;
case FIELDREF:
case METHODREF:
case INTERFACEMETHODREF:
stream.writeShort(indices1[i]);
stream.writeShort(indices2[i]);
break;
case STRING:
stream.writeShort(indices1[i]);
break;
case INTEGER:
stream.writeInt(((Integer)constants[i]).intValue());
break;
case FLOAT:
stream.writeFloat(((Float)constants[i]).floatValue());
break;
case LONG:
stream.writeLong(((Long)constants[i]).longValue());
i++;
break;
case DOUBLE:
stream.writeDouble(((Double)constants[i]).doubleValue());
i++;
break;
case NAMEANDTYPE:
stream.writeShort(indices1[i]);
stream.writeShort(indices2[i]);
break;
case UTF8:
stream.writeUTF((String)constants[i]);
break;
default:
throw new ClassFormatException("unknown constant tag");
}
}
}
}

@ -1,4 +1,4 @@
/* OptionHandler Copyright (C) 1999-2002 Jochen Hoenicke.
/* Handler Copyright (C) 1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -17,13 +17,13 @@
* $Id$
*/
package net.sf.jode.obfuscator;
package jode.bytecode;
///#def COLLECTIONS java.util
import java.util.Collection;
///#enddef
public interface OptionHandler {
public void setOption(String option, Collection values)
throws IllegalArgumentException;
/**
* A simple class containing the info about an exception handler
*/
public class Handler {
public Instruction start, end, catcher;
public String type;
}

@ -0,0 +1,37 @@
/* InnerClassInfo Copyright (C) 1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package jode.bytecode;
/**
* A simple class containing the info about an inner class.
*/
public class InnerClassInfo {
public String inner, outer;
public String name;
public int modifiers;
public InnerClassInfo(String inner, String outer, String name, int modif) {
this.inner = inner;
this.outer = outer;
this.name = name;
this.modifiers = modif;
}
}

@ -0,0 +1,492 @@
/* Instruction Copyright (C) 1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package jode.bytecode;
import java.util.Vector;
import java.util.Enumeration;
import jode.type.Type;
import jode.type.MethodType;
/**
* This class represents an instruction in the byte code.
*
* For simplicity currently most fields are public. You shouldn't change
* many of them, though.
*/
public class Instruction implements Opcodes{
public BytecodeInfo codeinfo;
/**
* The opcode of the instruction. We map some opcodes, e.g.
* <pre>
* iload_[0-3] -> iload, ldc_w -> ldc, wide iinc -> iinc.
* </pre>
*/
public int opcode;
/**
* If this opcode uses a local this gives the slot. This info is
* used when swapping locals.
*/
public int localSlot = -1;
/**
* Optional object data for this opcode. This is mostly used for
* method/field/class references, but also for a value array
* in a lookupswitch.
*/
public Object objData;
/**
* Optional integer data for this opcode. There are various uses
* for this.
*/
public int intData;
/**
* The address of this opcode.
*/
public int addr;
/**
* The length of this opcode. You shouldn't touch it, nor rely on
* it, since the length of some opcodes may change automagically
* (e.g. when changing localSlot iload_0 <-> iload 5)
*/
public int length;
/**
* If this is true, the instruction will never flow into the nextByAddr.
*/
public boolean alwaysJumps = false;
/**
* The successors of this opcodes, where flow may lead to
* (except that nextByAddr is implicit if !alwaysJump). The
* value null is equivalent to an empty array.
*/
public Instruction[] succs;
/**
* The predecessors of this opcode, orthogonal to the succs array.
* This must be null or a non empty array.
*/
public Instruction[] preds;
/**
* The next instruction in code order.
*/
public Instruction nextByAddr;
/**
* The previous instruction in code order, useful when changing
* the order.
*/
public Instruction prevByAddr;
/**
* You can use this field to add some info to each instruction.
* After using, you must set it to null again.
*/
public Object tmpInfo;
public Instruction(BytecodeInfo ci) {
this.codeinfo = ci;
}
public void addPredecessor(Instruction pred) {
if (preds == null) {
preds = new Instruction[] { pred };
return;
}
int predsLength = preds.length;
Instruction[] newPreds = new Instruction[predsLength+1];
System.arraycopy(preds, 0, newPreds, 0, predsLength);
newPreds[predsLength] = pred;
preds = newPreds;
}
public void removePredecessor(Instruction pred) {
/* Hopefully it doesn't matter if this is slow */
int predLength = preds.length;
if (predLength == 1) {
if (preds[0] != pred)
throw new jode.AssertError
("removing not existing predecessor");
preds = null;
} else {
Instruction[] newPreds = new Instruction[predLength-1];
int j;
for (j = 0; preds[j] != pred; j++)
newPreds[j] = preds[j];
System.arraycopy(preds, j+1, newPreds, j, predLength - j - 1);
preds = newPreds;
}
}
public Instruction insertInstruction() {
Instruction newInstr = new Instruction(codeinfo);
newInstr.addr = addr;
newInstr.prevByAddr = prevByAddr;
if (prevByAddr != null)
prevByAddr.nextByAddr = newInstr;
else
codeinfo.firstInstr = newInstr;
newInstr.nextByAddr = this;
prevByAddr = newInstr;
/* promote the predecessors to newInstr */
if (preds != null) {
for (int j=0; j < preds.length; j++)
for (int i=0; i < preds[j].succs.length; i++)
if (preds[j].succs[i] == this)
preds[j].succs[i] = newInstr;
newInstr.preds = preds;
preds = null;
}
return newInstr;
}
public Instruction appendInstruction() {
Instruction newInstr = new Instruction(codeinfo);
newInstr.addr = addr;
newInstr.nextByAddr = nextByAddr;
if (nextByAddr != null)
nextByAddr.prevByAddr = newInstr;
newInstr.prevByAddr = this;
nextByAddr = newInstr;
return newInstr;
}
/**
* Removes this instruction (as if it would be replaced by a nop).
*/
public void removeInstruction() {
/* remove from chained list */
if (prevByAddr != null)
prevByAddr.nextByAddr = nextByAddr;
else
codeinfo.firstInstr = nextByAddr;
if (nextByAddr != null)
nextByAddr.prevByAddr = prevByAddr;
/* remove predecessors of successors */
if (succs != null) {
for (int i=0; i < succs.length; i++)
succs[i].removePredecessor(this);
succs = null;
}
Instruction alternative = nextByAddr != null ? nextByAddr : prevByAddr;
/* remove the predecessors to alternative */
if (preds != null) {
for (int j=0; j < preds.length; j++)
for (int i=0; i < preds[j].succs.length; i++)
if (preds[j].succs[i] == this)
preds[j].succs[i] = alternative;
if (alternative.preds == null)
alternative.preds = preds;
else {
Instruction[] newPreds
= new Instruction[alternative.preds.length + preds.length];
System.arraycopy(preds, 0, newPreds, 0, preds.length);
System.arraycopy(alternative.preds, 0, newPreds, preds.length,
alternative.preds.length);
alternative.preds = newPreds;
}
preds = null;
}
/* adjust exception handlers */
Handler[] handlers = codeinfo.getExceptionHandlers();
for (int i=0; i< handlers.length; i++) {
if (handlers[i].start == this)
handlers[i].start = nextByAddr;
if (handlers[i].end == this)
handlers[i].end = prevByAddr;
if (handlers[i].catcher == this)
handlers[i].catcher = nextByAddr;
if (handlers[i].start == null
|| handlers[i].end == null
|| handlers[i].end.nextByAddr == handlers[i].start) {
/* Remove the handler.
* This is very seldom, so we can make it slow */
Handler[] newHandlers = new Handler[handlers.length - 1];
System.arraycopy(handlers, 0, newHandlers, 0, i);
System.arraycopy(handlers, i+1, newHandlers, i,
handlers.length - (i+1));
handlers = newHandlers;
codeinfo.setExceptionHandlers(newHandlers);
i--;
}
}
/* adjust local variable table and line number table */
LocalVariableInfo[] lvt = codeinfo.getLocalVariableTable();
if (lvt != null) {
for (int i=0; i< lvt.length; i++) {
if (lvt[i].start == this)
lvt[i].start = nextByAddr;
if (lvt[i].end == this)
lvt[i].end = prevByAddr;
if (lvt[i].start == null
|| lvt[i].end == null
|| lvt[i].end.nextByAddr == lvt[i].start) {
/* Remove the local variable info.
* This is very seldom, so we can make it slow */
LocalVariableInfo[] newLVT =
new LocalVariableInfo[lvt.length - 1];
System.arraycopy(lvt, 0, newLVT, 0, i);
System.arraycopy(lvt, i+1, newLVT, i,
newLVT.length - i);
lvt = newLVT;
codeinfo.setLocalVariableTable(newLVT);
i--;
}
}
}
LineNumber[] lnt = codeinfo.getLineNumberTable();
if (lnt != null) {
for (int i=0; i< lnt.length; i++) {
if (lnt[i].start == this)
lnt[i].start = nextByAddr;
if (lnt[i].start == null
|| (i+1 < lnt.length && lnt[i].start == lnt[i+1].start)) {
/* Remove the line number.
* This is very seldom, so we can make it slow */
LineNumber[] newLNT =
new LineNumber[lnt.length - 1];
System.arraycopy(lnt, 0, newLNT, 0, i);
System.arraycopy(lnt, i+1, newLNT, i,
newLNT.length - i);
lnt = newLNT;
codeinfo.setLineNumberTable(newLNT);
i--;
}
}
}
}
/**
* This returns the number of stack entries this instruction
* pushes and pops from the stack. The result fills the given
* array.
*
* @param poppush an array of two ints. The first element will
* get the number of pops, the second the number of pushes.
*/
public void getStackPopPush(int[] poppush)
/*{ require { poppush != null && poppush.length == 2
:: "poppush must be an array of two ints" } } */
{
byte delta = stackDelta[opcode];
if (delta < 0x40) {
poppush[0] = delta & 7;
poppush[1] = delta >> 3;
} else {
switch (opcode) {
case opc_invokevirtual:
case opc_invokespecial:
case opc_invokestatic:
case opc_invokeinterface: {
Reference ref = (Reference) objData;
MethodType mt = (MethodType) Type.tType(ref.getType());
poppush[1] = mt.getReturnType().stackSize();
poppush[0] = opcode != opc_invokestatic ? 1 : 0;
for (int i = mt.getParameterTypes().length-1; i >= 0; i--)
poppush[0] += mt.getParameterTypes()[i].stackSize();
break;
}
case opc_putfield:
case opc_putstatic: {
Reference ref = (Reference) objData;
poppush[1] = 0;
poppush[0] = Type.tType(ref.getType()).stackSize();
if (opcode == opc_putfield)
poppush[0]++;
break;
}
case opc_getstatic:
case opc_getfield: {
Reference ref = (Reference) objData;
poppush[1] = Type.tType(ref.getType()).stackSize();
poppush[0] = opcode == opc_getfield ? 1 : 0;
break;
}
case opc_multianewarray: {
poppush[1] = 1;
poppush[0] = prevByAddr.intData;
break;
}
default:
throw new jode.AssertError("Unknown Opcode: "+opcode);
}
}
}
public Instruction findMatchingPop() {
int poppush[] = new int[2];
getStackPopPush(poppush);
int count = poppush[1];
Instruction instr = this;
while (true) {
if (instr.succs != null || instr.alwaysJumps)
return null;
instr = instr.nextByAddr;
if (instr.preds != null)
return null;
instr.getStackPopPush(poppush);
if (count == poppush[0])
return instr;
count += poppush[1] - poppush[0];
}
}
public Instruction findMatchingPush() {
int count = 0;
Instruction instr = this;
int poppush[] = new int[2];
while (true) {
if (instr.preds != null)
return null;
instr = instr.prevByAddr;
if (instr == null || instr.succs != null || instr.alwaysJumps)
return null;
instr.getStackPopPush(poppush);
if (count < poppush[1]) {
return count == 0 ? instr : null;
}
count += poppush[0] - poppush[1];
}
}
public String getDescription() {
StringBuffer result = new StringBuffer(String.valueOf(addr))
.append('_').append(Integer.toHexString(hashCode()))
.append(": ").append(opcodeString[opcode]);
switch (opcode) {
case opc_iload: case opc_lload:
case opc_fload: case opc_dload: case opc_aload:
case opc_istore: case opc_lstore:
case opc_fstore: case opc_dstore: case opc_astore:
case opc_ret:
result.append(" ").append(localSlot);
break;
case opc_iinc:
result.append(" ").append(localSlot).append(" ").append(intData);
break;
case opc_ldc: case opc_ldc2_w:
case opc_getstatic: case opc_getfield:
case opc_putstatic: case opc_putfield:
case opc_invokespecial: case opc_invokestatic: case opc_invokevirtual:
case opc_new:
case opc_checkcast:
case opc_instanceof:
result.append(" ").append(objData);
break;
case opc_anewarray:
case opc_newarray:
result.append(" ").append(((String)objData).substring(1));
break;
case opc_multianewarray:
case opc_invokeinterface:
result.append(" ").append(objData).append(" ").append(intData);
break;
case opc_ifeq: case opc_ifne:
case opc_iflt: case opc_ifge:
case opc_ifgt: case opc_ifle:
case opc_if_icmpeq: case opc_if_icmpne:
case opc_if_icmplt: case opc_if_icmpge:
case opc_if_icmpgt: case opc_if_icmple:
case opc_if_acmpeq: case opc_if_acmpne:
case opc_ifnull: case opc_ifnonnull:
case opc_goto:
case opc_jsr:
result.append(" ").append(succs[0].addr);
break;
}
return result.toString();
}
public String toString() {
return ""+addr+"_"+Integer.toHexString(hashCode());
}
public final static byte[] stackDelta;
static {
stackDelta = new byte[202];
for (int i=0; i < 202; i++) {
stackDelta[i] = (byte) "\000\010\010\010\010\010\010\010\010\020\020\010\010\010\020\020\010\010\010\010\020\010\020\010\020\010\010\010\010\010\020\020\020\020\010\010\010\010\020\020\020\020\010\010\010\010\012\022\012\022\012\012\012\012\001\002\001\002\001\001\001\001\001\002\002\002\002\001\001\001\001\002\002\002\002\001\001\001\001\003\004\003\004\003\003\003\003\001\002\021\032\043\042\053\064\022\012\024\012\024\012\024\012\024\012\024\012\024\012\024\012\024\012\024\012\024\011\022\011\022\012\023\012\023\012\023\012\024\012\024\012\024\000\021\011\021\012\012\022\011\021\021\012\022\012\011\011\011\014\012\012\014\014\001\001\001\001\001\001\002\002\002\002\002\002\002\002\000\010\000\001\001\001\002\001\002\001\000\100\100\100\100\100\100\100\100\177\010\011\011\011\001\011\011\001\001\177\100\001\001\000\010".charAt(i);
}
}
/* stackDelta contains \100 if stack count of opcode is variable
* \177 if opcode is illegal, or 8*stack_push + stack_pop otherwise
* The above values are extracted from following list with:
* perl -ne'/"(.*)"/ and print $1'
*
* "\000" // nop
* "\010\010\010\010\010\010\010\010" // aconst_null, iconst_m?[0-5]
* "\020\020\010\010\010\020\020" // [lfd]const_[0-2]
* "\010\010\010\010\020" // sipush bipush ldcx
* "\010\020\010\020\010" // [ilfda]load
* "\010\010\010\010"
* "\020\020\020\020"
* "\010\010\010\010"
* "\020\020\020\020"
* "\010\010\010\010"
* "\012\022\012\022\012\012\012\012" // [ilfdabcs]aload
* "\001\002\001\002\001" // [ilfda]store
* "\001\001\001\001"
* "\002\002\002\002"
* "\001\001\001\001"
* "\002\002\002\002"
* "\001\001\001\001"
* "\003\004\003\004\003\003\003\003" // [ilfdabcs]astore
* "\001\002" // pop
* "\021\032\043\042\053\064" // dup2?(_x[12])?
* "\022" // swap
* "\012\024\012\024" // [ilfd]add
* "\012\024\012\024" // [ilfd]sub
* "\012\024\012\024" // [ilfd]mul
* "\012\024\012\024" // [ilfd]div
* "\012\024\012\024" // [ilfd]rem
* "\011\022\011\022" // [ilfd]neg
* "\012\023\012\023\012\023" // [il]u?sh[lr]
* "\012\024\012\024\012\024" // [il](and|or|xor)
* "\000" // opc_iinc
* "\021\011\021" // i2[lfd]
* "\012\012\022" // l2[ifd]
* "\011\021\021" // f2[ild]
* "\012\022\012" // d2[ilf]
* "\011\011\011" // i2[bcs]
* "\014\012\012\014\014" // [lfd]cmp.?
* "\001\001\001\001\001\001" // if..
* "\002\002\002\002\002\002" // if_icmp..
* "\002\002" // if_acmp..
* "\000\010\000\001\001" // goto,jsr,ret, .*switch
* "\001\002\001\002\001\000" // [ilfda]?return
* "\100\100\100\100" // (get/put)(static|field)
* "\100\100\100\100" // invoke.*
* "\177\010\011\011\011" // 186 - 190
* "\001\011\011\001\001" // 191 - 195
* "\177\100\001\001" // 196 - 199
* "\000\010" // goto_w, jsr_w
*/
}

@ -0,0 +1,29 @@
/* LineNumber Copyright (C) 1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package jode.bytecode;
/**
* A simple class containing the info of the LineNumberTable
*/
public class LineNumber {
public Instruction start;
public int linenr;
}

@ -0,0 +1,30 @@
/* LocalVariableInfo Copyright (C) 1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package jode.bytecode;
/**
* A simple class containing the info of the LocalVariableTable
*/
public class LocalVariableInfo {
public Instruction start, end;
public String name, type;
public int slot;
}

@ -0,0 +1,46 @@
## Input file for automake to generate the Makefile.in used by configure
JAR = @JAR@
JAVAC = @JAVAC@
JIKES = @JIKES@
CLASSPATH = @CLASSPATH@
CLASSLIB = @CLASSLIB@
BUILD_CLASSPATH = $(top_srcdir):$(top_builddir):$(CLASSPATH):$(CLASSLIB)
MY_JAVA_FILES = \
BinaryInfo.java \
BytecodeInfo.java \
ClassFormatException.java \
ClassInfo.java \
ConstantPool.java \
FieldInfo.java \
GrowableConstantPool.java \
Handler.java \
InnerClassInfo.java \
Instruction.java \
LineNumber.java \
LocalVariableInfo.java \
MethodInfo.java \
Opcodes.java \
Reference.java \
SearchPath.java
noinst_DATA = $(MY_JAVA_FILES:.java=.class)
EXTRA_DIST = $(MY_JAVA_FILES)
if HAVE_JIKES
@QUOTE@-include $(top_builddir)/jode/.java.deps
%.class: %.java
$(JIKES) -classpath $(BUILD_CLASSPATH):$(CLASSLIB) +M=$(top_builddir)/jode/.java.deps -d $(top_builddir) $<
else
%.class: %.java
$(JAVAC) -classpath $(BUILD_CLASSPATH):$(CLASSLIB) -depend -d $(top_builddir) $<
endif
clean-local:
@rm -f *.class

@ -0,0 +1,227 @@
/* MethodInfo Copyright (C) 1998-1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package jode.bytecode;
import java.io.*;
import java.lang.reflect.Modifier;
public class MethodInfo extends BinaryInfo {
ClassInfo clazzInfo;
int modifier;
String name;
String typeSig;
BytecodeInfo bytecode;
String[] exceptions;
boolean syntheticFlag;
boolean deprecatedFlag;
public MethodInfo(ClassInfo ci) {
clazzInfo = ci;
}
public MethodInfo(ClassInfo ci,
String name, String typeSig, int modifier) {
this.clazzInfo = ci;
this.name = name;
this.typeSig = typeSig;
this.modifier = modifier;
}
protected void readAttribute(String name, int length, ConstantPool cp,
DataInputStream input,
int howMuch) throws IOException {
if ((howMuch & ALL_ATTRIBUTES) != 0 && name.equals("Code")) {
bytecode = new BytecodeInfo(this);
bytecode.read(cp, input);
} else if ((howMuch & ALL_ATTRIBUTES) != 0
&& name.equals("Exceptions")) {
int count = input.readUnsignedShort();
exceptions = new String[count];
for (int i=0; i< count; i++)
exceptions[i] = cp.getClassName(input.readUnsignedShort());
if (length != 2 * (count + 1))
throw new ClassFormatException
("Exceptions attribute has wrong length");
} else if (name.equals("Synthetic")) {
syntheticFlag = true;
if (length != 0)
throw new ClassFormatException
("Synthetic attribute has wrong length");
} else if (name.equals("Deprecated")) {
deprecatedFlag = true;
if (length != 0)
throw new ClassFormatException
("Deprecated attribute has wrong length");
} else
super.readAttribute(name, length, cp, input, howMuch);
}
public void read(ConstantPool constantPool,
DataInputStream input, int howMuch) throws IOException {
modifier = input.readUnsignedShort();
name = constantPool.getUTF8(input.readUnsignedShort());
typeSig = constantPool.getUTF8(input.readUnsignedShort());
readAttributes(constantPool, input, howMuch);
}
public void reserveSmallConstants(GrowableConstantPool gcp) {
if (bytecode != null)
bytecode.reserveSmallConstants(gcp);
}
public void prepareWriting(GrowableConstantPool gcp) {
gcp.putUTF8(name);
gcp.putUTF8(typeSig);
if (bytecode != null) {
gcp.putUTF8("Code");
bytecode.prepareWriting(gcp);
}
if (exceptions != null) {
gcp.putUTF8("Exceptions");
for (int i=0; i< exceptions.length; i++)
gcp.putClassName(exceptions[i]);
}
if (syntheticFlag)
gcp.putUTF8("Synthetic");
if (deprecatedFlag)
gcp.putUTF8("Deprecated");
prepareAttributes(gcp);
}
protected int getKnownAttributeCount() {
int count = 0;
if (bytecode != null)
count++;
if (exceptions != null)
count++;
if (syntheticFlag)
count++;
if (deprecatedFlag)
count++;
return count;
}
public void writeKnownAttributes(GrowableConstantPool gcp,
DataOutputStream output)
throws IOException {
if (bytecode != null) {
output.writeShort(gcp.putUTF8("Code"));
output.writeInt(bytecode.getSize());
bytecode.write(gcp, output);
}
if (exceptions != null) {
int count = exceptions.length;
output.writeShort(gcp.putUTF8("Exceptions"));
output.writeInt(2 + count * 2);
output.writeShort(count);
for (int i=0; i< count; i++)
output.writeShort(gcp.putClassName(exceptions[i]));
}
if (syntheticFlag) {
output.writeShort(gcp.putUTF8("Synthetic"));
output.writeInt(0);
}
if (deprecatedFlag) {
output.writeShort(gcp.putUTF8("Deprecated"));
output.writeInt(0);
}
}
public void write(GrowableConstantPool constantPool,
DataOutputStream output) throws IOException {
output.writeShort(modifier);
output.writeShort(constantPool.putUTF8(name));
output.writeShort(constantPool.putUTF8(typeSig));
writeAttributes(constantPool, output);
}
public ClassInfo getClazzInfo() {
return clazzInfo;
}
public String getName() {
return name;
}
public String getType() {
return typeSig;
}
public int getModifiers() {
return modifier;
}
public boolean isStatic() {
return Modifier.isStatic(modifier);
}
public boolean isSynthetic() {
return syntheticFlag;
}
public boolean isDeprecated() {
return deprecatedFlag;
}
public BytecodeInfo getBytecode() {
return bytecode;
}
public String[] getExceptions() {
return exceptions;
}
public void setName(String newName) {
name = newName;
}
public void setType(String newType) {
typeSig = newType;
}
public void setModifiers(int newModifier) {
modifier = newModifier;
}
public void setSynthetic(boolean flag) {
syntheticFlag = flag;
}
public void setDeprecated(boolean flag) {
deprecatedFlag = flag;
}
public void setBytecode(BytecodeInfo newBytecode) {
clazzInfo.loadInfo(ALL_ATTRIBUTES);
bytecode = newBytecode;
}
public void setExceptions(String[] newExceptions) {
clazzInfo.loadInfo(ALL_ATTRIBUTES);
exceptions = newExceptions;
}
public String toString() {
return "Method "+Modifier.toString(modifier)+" "+
typeSig + " " + clazzInfo.getName() + "."+ name;
}
}

@ -1,7 +1,7 @@
/* Opcodes Copyright (C) 1998-2002 Jochen Hoenicke.
/* Opcodes Copyright (C) 1998-1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
@ -10,14 +10,14 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; see the file COPYING.LESSER. If not, write to
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package net.sf.jode.bytecode;
package jode.bytecode;
/**
* This is an interface containing the constants for the byte code opcodes.
@ -226,8 +226,6 @@ public interface Opcodes {
public final static int opc_goto_w = 200;
public final static int opc_jsr_w = 201;
public final static int opc_breakpoint = 202;
public final static int opc_impdep1 = 254;
public final static int opc_impdep2 = 255;
public final static String[] opcodeString = {
"nop", "aconst_null", "iconst_m1", "iconst_0", "iconst_1",
@ -267,14 +265,4 @@ public interface Opcodes {
public final static String newArrayTypes = "ZCFDBSIJ";
public final static Object[] constants = {
null,
new Integer(-1), new Integer(0), new Integer(1),
new Integer(2), new Integer(3), new Integer(4), new Integer(5),
new Long(0), new Long(1),
new Float(0), new Float(1), new Float(2),
new Double(0), new Double(1)
};
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save