Compare commits
14 Commits
Author | SHA1 | Date |
---|---|---|
jochen | b863984781 | 25 years ago |
jochen | d49e59a3ef | 25 years ago |
jochen | f6f2987fad | 25 years ago |
jochen | 62e7cb80d6 | 25 years ago |
jochen | ed0f34efba | 25 years ago |
jochen | 8377de22ad | 25 years ago |
jochen | ddad164a2e | 25 years ago |
jochen | 20d93c44fe | 25 years ago |
jochen | 4ae713d9a6 | 25 years ago |
jochen | 2d2c71bdb9 | 25 years ago |
(no author) | e3d7a55d64 | 25 years ago |
jochen | 999834f14d | 25 years ago |
jochen | fc1da2077a | 25 years ago |
(no author) | 70a8181fce | 25 years ago |
@ -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 +0,0 @@ |
|||||||
*.class |
|
@ -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,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,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 |
Before installing, make sure you have a java compiler (e.g javac or |
||||||
developement kit installed. If you want to run this program you only |
jikes) and the java 1.1 runtime class library installed. If you want |
||||||
need the java runtime environment. Version 1.1 is quite old, I |
to run this program you need at least a 1.1 compatible java virtual |
||||||
recommend using Java 2 (jdk1.2 or above). You need perl if you want |
machine. There are some bugs in javac included in the SUN JDK 1.1, it |
||||||
to compile a 1.1 version. |
won't work. |
||||||
|
|
||||||
This package was designed to use the ANT from the jakarta.apache.org |
This package was designed to use the GNU standard for configuration |
||||||
tools. I assume you have installed it correctly. |
and makefiles. To build and install do the following: |
||||||
|
|
||||||
Take some time to edit config.props. There are a few options you need |
0). Make sure that you have all libraries that are needed in you |
||||||
to take care of. (Unfortunately ant can't test for executables). |
classpath. You need gnu.getopt, and if you have JDK 1.1 you also need |
||||||
|
the collection classes and swing for 1.1. |
||||||
Now you are ready to invoke ant. There are many possible targets, here |
|
||||||
are the most useful ones: |
1). Run "aclocal && autoconf && automake --add-missing". |
||||||
|
|
||||||
all builds class files and documentation. |
2). Run the "configure" script to configure the package. There are |
||||||
build builds class files only (autodetects java version). |
various options you might want to pass to configure to control how the |
||||||
build-1.1 builds JDK1.1 class files. |
package is built. "configure --help" will give a complete list. |
||||||
doc builds documentation. |
|
||||||
dist creates all release files. |
If you have jikes, you should specify it with --with-jikes. You can |
||||||
test does some self tests. You need to have junit installed for this. |
give a path to the directory where it resides, otherwise it is |
||||||
clean cleans everything that doesn't belong to the source distribution. |
searched in the path. |
||||||
cvsclean cleans everything that doesn't belong into the cvs repository. |
|
||||||
|
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,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 -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 |
</body> |
||||||
java. This package is freely available under the GNU General Public |
</html> |
||||||
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. |
|
||||||
|
@ -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> |
|
@ -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 |
||||||
|
]) |
@ -1,5 +1,4 @@ |
|||||||
## Input file for automake to generate the Makefile.in used by configure
|
## Input file for automake to generate the Makefile.in used by configure
|
||||||
|
|
||||||
bin_SCRIPTS = jode
|
bin_SCRIPTS = jode
|
||||||
EXTRA_DIST = jode.bat.in jode.in
|
|
||||||
|
|
||||||
|
@ -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 |
|
@ -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='<b><a href="http://jode.sourceforge.net/">Jode</a> ${version}</b><br><font size="-2">Build ${date}</font>' |
|
||||||
overview="${src}/net/sf/jode/overview.html" |
|
||||||
bottom='Copyright &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 |
|
@ -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 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 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><init></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 © 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> |
|
Before Width: | Height: | Size: 126 B |
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 |
|
||||||
|
|
Before Width: | Height: | Size: 192 B |
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&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 -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> |
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 -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&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 © 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 © 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(" ", " ", $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) |
|
||||||
# |
|
Before Width: | Height: | Size: 1.3 KiB |
@ -1,250 +0,0 @@ |
|||||||
<if we_want_a_menu> |
|
||||||
<p>On this page:<br> |
|
||||||
<a href="#decompiler">Decompiler</a><br> |
|
||||||
<a href="#cmdline">Command Line</a><br> |
|
||||||
<a href="#awt">AWT Interface</a><br> |
|
||||||
<a href="#swing">Swing Interface</a><br> |
|
||||||
<a href="#java">Java 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&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 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><init>.()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.<init>.()V" }, |
|
||||||
new WildCard { value = "org.resources.Bundle*.<init>.()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> |
|
Before Width: | Height: | Size: 1.0 KiB |
@ -0,0 +1,4 @@ |
|||||||
|
Makefile |
||||||
|
Makefile.in |
||||||
|
.java.deps |
||||||
|
jode.jar |
@ -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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -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(); |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |