Some copyright/documentation updates

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


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1383 379699f6-c40d-0410-875b-85095c16579e
master
hoenicke 21 years ago
parent 033d9d57e5
commit 487a4b49d9
  1. 26
      jode/ChangeLog
  2. 6
      jode/build.xml
  3. 2
      jode/src/net/sf/jode/GlobalOptions.java
  4. 39
      jode/src/net/sf/jode/bytecode/BasicBlockReader.java
  5. 82
      jode/src/net/sf/jode/bytecode/BinaryInfo.java
  6. 30
      jode/src/net/sf/jode/bytecode/ClassInfo.java
  7. 6
      jode/src/net/sf/jode/bytecode/ClassPath.java
  8. 29
      jode/src/net/sf/jode/bytecode/FieldInfo.java
  9. 29
      jode/src/net/sf/jode/bytecode/MethodInfo.java
  10. 17
      jode/src/net/sf/jode/bytecode/TypeSignature.java
  11. 4
      jode/src/net/sf/jode/decompiler/MethodAnalyzer.java
  12. 2
      jode/src/net/sf/jode/expr/InvokeOperator.java
  13. 61
      jode/src/net/sf/jode/flow/FlowBlock.java

@ -1,3 +1,29 @@
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> 2004-08-05 Jochen Hoenicke <hoenicke@marge.Informatik.Uni-Oldenburg.DE>
* build.xml: replace execon with apply. * build.xml: replace execon with apply.

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="iso-8859-1"?> <?xml version="1.0" encoding="iso-8859-1"?>
<!-- Jakarta-Ant build file for jode, Copyright (C) 1999-2001 Jochen Hoenicke. <!-- Jakarta-Ant build file for jode, Copyright (C) 1999-2004 Jochen Hoenicke.
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -146,6 +146,7 @@
<mkdir dir="${build}"/> <mkdir dir="${build}"/>
<javac srcdir="${src}" <javac srcdir="${src}"
destdir="${build}" destdir="${build}"
debug="true"
classpathref="project.classpath" classpathref="project.classpath"
deprecation="on"> deprecation="on">
<exclude name="net/sf/jode/obfuscator/modules/RemovePopAnalyzer.java"/> <exclude name="net/sf/jode/obfuscator/modules/RemovePopAnalyzer.java"/>
@ -272,7 +273,7 @@
windowtitle="Jode ${version} API Specification" windowtitle="Jode ${version} API Specification"
header='&lt;b&gt;&lt;a href="http://jode.sourceforge.net/"&gt;Jode&lt;/a&gt; ${version}&lt;/b&gt;&lt;br&gt;&lt;font size="-2"&gt;Build ${date}&lt;/font&gt;' header='&lt;b&gt;&lt;a href="http://jode.sourceforge.net/"&gt;Jode&lt;/a&gt; ${version}&lt;/b&gt;&lt;br&gt;&lt;font size="-2"&gt;Build ${date}&lt;/font&gt;'
overview="${src}/net/sf/jode/overview.html" overview="${src}/net/sf/jode/overview.html"
bottom='Copyright &amp;copy; 1998-2001 by Jochen Hoenicke.' bottom='Copyright &amp;copy; 1998-2004 by Jochen Hoenicke.'
sourcepath="${src}" sourcepath="${src}"
destdir="${api.doc}" destdir="${api.doc}"
use="yes"> use="yes">
@ -298,6 +299,7 @@
<mkdir dir="${test.build}"/> <mkdir dir="${test.build}"/>
<javac srcdir="${test.src}" <javac srcdir="${test.src}"
destdir="${test.build}" destdir="${test.build}"
debug="true"
classpathref="project.classpath" classpathref="project.classpath"
classpath="${build}" classpath="${build}"
deprecation="on"> deprecation="on">

@ -25,7 +25,7 @@ public class GlobalOptions {
public final static String version = "@VERSION@"; public final static String version = "@VERSION@";
public final static String email = "jochen@gnu.org"; public final static String email = "jochen@gnu.org";
public final static String copyright = public final static String copyright =
"Jode (c) 1998-2001 Jochen Hoenicke <"+email+">"; "Jode (c) 1998-2004 Jochen Hoenicke <"+email+">";
public final static String URL = "http://jode.sourceforge.net/"; public final static String URL = "http://jode.sourceforge.net/";
public static PrintWriter err = new PrintWriter(System.err, true); public static PrintWriter err = new PrintWriter(System.err, true);

@ -224,25 +224,27 @@ class BasicBlockReader implements Opcodes {
private Handler[] convertHandlers() { private Handler[] convertHandlers() {
int newCount = 0; int newCount = 0;
for (int i=0; i < handlers.length; i++) { for (int i=0; i < handlers.length; i++) {
while (handlers[i].start < handlers[i].end
&& infos[handlers[i].start].blockNr == -1)
handlers[i].start = infos[handlers[i].start].nextAddr;
if (handlers[i].start == handlers[i].end)
continue;
while (handlers[i].end < infos.length
&& infos[handlers[i].end].blockNr == -1)
handlers[i].end = infos[handlers[i].end].nextAddr;
if ((infos[handlers[i].catcher].flags & IS_REACHABLE) != 0) if ((infos[handlers[i].catcher].flags & IS_REACHABLE) != 0)
newCount++; newCount++;
} }
Handler[] newHandlers = new Handler[newCount]; Handler[] newHandlers = new Handler[newCount];
int ptr = 0; int ptr = 0;
for (int i=0; i<handlers.length; i++) { for (int i=0; i<handlers.length; i++) {
int start = handlers[i].start; if (handlers[i].start < handlers[i].end
while (infos[start].blockNr == -1) && (infos[handlers[i].catcher].flags & IS_REACHABLE) != 0) {
start = infos[start].nextAddr; int endBlock = handlers[i].end < infos.length
int end = handlers[i].end; ? infos[handlers[i].end].blockNr : blocks.length;
while (end < infos.length
&& infos[end].blockNr == -1)
end = infos[end].nextAddr;
int endBlock = end < infos.length
? infos[end].blockNr : blocks.length;
if ((infos[handlers[i].catcher].flags & IS_REACHABLE) != 0) {
newHandlers[ptr++] = new Handler newHandlers[ptr++] = new Handler
(blocks[infos[start].blockNr], (blocks[infos[handlers[i].start].blockNr],
blocks[endBlock - 1], blocks[endBlock - 1],
getSuccBlock(handlers[i].catcher), getSuccBlock(handlers[i].catcher),
handlers[i].type); handlers[i].type);
@ -856,6 +858,17 @@ class BasicBlockReader implements Opcodes {
handlers[i].type = (index == 0) ? null handlers[i].type = (index == 0) ? null
: cp.getClassName(index); : cp.getClassName(index);
if (i > 0 && handlers[i].start == handlers[i-1].end
&& handlers[i].catcher == handlers[i-1].catcher
&& handlers[i].type == handlers[i-1].type) {
/* Javac 1.4 splits handlers at return instruction
* (see below). We merge them together here.
*/
handlers[i-1].end = handlers[i].end;
handlersLength--;
i--;
}
if ((GlobalOptions.debuggingFlags if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_BYTECODE) != 0) & GlobalOptions.DEBUG_BYTECODE) != 0)
GlobalOptions.err.println("Handler "+handlers[i].start GlobalOptions.err.println("Handler "+handlers[i].start
@ -870,6 +883,7 @@ class BasicBlockReader implements Opcodes {
*/ */
handlersLength--; handlersLength--;
i--; i--;
continue;
} }
if (handlers[i].start <= handlers[i].catcher if (handlers[i].start <= handlers[i].catcher
@ -883,6 +897,7 @@ class BasicBlockReader implements Opcodes {
if (handlers[i].start == handlers[i].catcher) { if (handlers[i].start == handlers[i].catcher) {
handlersLength--; handlersLength--;
i--; i--;
continue;
} else { } else {
handlers[i].end = handlers[i].catcher; handlers[i].end = handlers[i].catcher;
} }

@ -61,6 +61,79 @@ import java.util.Iterator;
* @author Jochen Hoenicke * @author Jochen Hoenicke
*/ */
public class BinaryInfo { public class BinaryInfo {
/**
* The bit mask representing public modifier.
*/
public static int ACC_PUBLIC = 0x0001;
/**
* The bit mask representing private modifier.
*/
public static int ACC_PRIVATE = 0x0002;
/**
* The bit mask representing protected modifier.
*/
public static int ACC_PROTECTED = 0x0004;
/**
* The bit mask representing static modifier.
*/
public static int ACC_STATIC = 0x0008;
/**
* The bit mask representing final modifier.
*/
public static int ACC_FINAL = 0x0010;
/**
* The bit mask representing the ACC_SUPER modifier for classes.
* This is a special modifier that only has historic meaning. Every
* class should have this set.
*/
public static int ACC_SUPER = 0x0020;
/**
* The bit mask representing volatile modifier for fields.
*/
public static int ACC_VOLATILE = 0x0040;
/**
* The bit mask representing synthetic bridge method. This is
* used when a non-generic method overrides a generic method of
* super class/interface.
*/
public static int ACC_BRIDGE = 0x0040;
/**
* The bit mask representing transient fields.
*/
public static int ACC_TRANSIENT = 0x0080;
/**
* The bit mask representing varargs methods.
*/
public static int ACC_VARARGS = 0x0080;
/**
* The bit mask representing enum fields.
*/
public static int ACC_ENUM = 0x0100;
/**
* The bit mask representing native methods.
*/
public static int ACC_NATIVE = 0x0100;
/**
* The bit mask representing interfaces.
*/
public static int ACC_INTERFACE = 0x0200;
/**
* The bit mask representing abstract modifier.
*/
public static int ACC_ABSTRACT = 0x0400;
/**
* The bit mask representing annotation classes.
*/
public static int ACC_ANNOTATION = 0x0800;
/**
* The bit mask representing strictfp modifier.
*/
public static int ACC_STRICT = 0x0800;
/**
* The bit mask representing synthetic fields/methods and classes.
*/
public static int ACC_SYNTHETIC = 0x1000;
private Map unknownAttributes = null; private Map unknownAttributes = null;
void skipAttributes(DataInputStream input) throws IOException { void skipAttributes(DataInputStream input) throws IOException {
@ -174,8 +247,8 @@ public class BinaryInfo {
/** /**
* Drops information from this info. Override this to drop your * Drops information from this info. Override this to drop your
* own info and don't forget to call the method of the super class. * own info and don't forget to call the method of the super class.
* @param howMuch the constant that was given to the {@link * @param keep the constant representing how much information we
* ClassInfo#drop} function when loading this class. * should keep (see {@link ClassInfo#load}).
*/ */
protected void drop(int keep) { protected void drop(int keep) {
if (keep < ClassInfo.ALL) if (keep < ClassInfo.ALL)
@ -214,13 +287,14 @@ public class BinaryInfo {
* Overwrite this method if you want to add your own attributes. * Overwrite this method if you want to add your own attributes.
* All constants you need from the growable constant pool must * All constants you need from the growable constant pool must
* have been previously registered by the {@link #prepareAttributes} * have been previously registered by the {@link #prepareAttributes}
* method.</p> * method. This method must not add new constants to the pool</p>
* *
* First call the method of the super class. Afterwrites write * First call the method of the super class. Afterwrites write
* each of your own attributes including the attribute header * each of your own attributes including the attribute header
* (name and length entry). * (name and length entry).
* *
* @param gcp The growable constant pool, which is not growable anymore. * @param constantPool The growable constant pool, which is not
* growable anymore (see above).
* @param output the data output stream. You must write exactly * @param output the data output stream. You must write exactly
* as many bytes to it as you have told with the {@link * as many bytes to it as you have told with the {@link
* #getAttributeSize} method. * #getAttributeSize} method.

@ -128,6 +128,9 @@ import java.lang.reflect.Modifier;
* Every class (resp. interfaces) can implement (resp. extend) * Every class (resp. interfaces) can implement (resp. extend)
* zero or more interfaces. * zero or more interfaces.
* </dd> * </dd>
* <dt>signature</dt><dd>The classes super class and interfaces with
* template information.</dd>
*
* <dt>fields</dt><dd> * <dt>fields</dt><dd>
* Fields are represented as {@link FieldInfo} objects. * Fields are represented as {@link FieldInfo} objects.
* </dd> * </dd>
@ -569,13 +572,13 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
} else if (howMuch >= ClassInfo.OUTERCLASS } else if (howMuch >= ClassInfo.OUTERCLASS
&& name.equals("InnerClasses")) { && name.equals("InnerClasses")) {
readInnerClassesAttribute(length, cp, input); readInnerClassesAttribute(length, cp, input);
} else if (name.equals("Signature")) {
signature = cp.getUTF8(input.readUnsignedShort());
} else if (name.equals("Deprecated")) { } else if (name.equals("Deprecated")) {
deprecatedFlag = true; deprecatedFlag = true;
if (length != 0) if (length != 0)
throw new ClassFormatException throw new ClassFormatException
("Deprecated attribute has wrong length"); ("Deprecated attribute has wrong length");
} else if (name.equals("Signature")) {
signature = cp.getUTF8(input.readUnsignedShort());
} else } else
super.readAttribute(name, length, cp, input, howMuch); super.readAttribute(name, length, cp, input, howMuch);
} }
@ -1189,13 +1192,34 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
return interfaces; return interfaces;
} }
/**
* Gets the type signature including template information of the class.
* <b>WARNING:</b> This field may disappear and merged into getType later.
* @return the type signature.
* @see TypeSignature
*/
public String getSignature() {
if (status < HIERARCHY)
throw new IllegalStateException("status is "+status);
if (signature != null)
return signature;
StringBuffer sb = new StringBuffer();
sb.append('L').append(superclass.getName().replace('.','/'))
.append(";");
for (int i = 0; i < interfaces.length; i++) {
sb.append('L').append(interfaces[i].getName().replace('.','/'))
.append(";");
}
return sb.toString();
}
/** /**
* Gets the modifiers of this class, e.g. public or abstract. The * Gets the modifiers of this class, e.g. public or abstract. The
* information is only available if at least {@link #HIERARCHY} is * information is only available if at least {@link #HIERARCHY} is
* loaded. * loaded.
* @return a bitboard of the modifiers. * @return a bitboard of the modifiers.
* @see Class#getModifiers * @see Class#getModifiers
* @see Modifier * @see BinaryInfo#ACC_PUBLIC ACC_* fields in BinaryInfo
*/ */
public int getModifiers() { public int getModifiers() {
if (modifiers == -1) if (modifiers == -1)

@ -518,7 +518,7 @@ public class ClassPath {
* description for more information, which kind of paths are * description for more information, which kind of paths are
* supported. When a class or a file is not found in the class * supported. When a class or a file is not found in the class
* path the fallback is used. * path the fallback is used.
* @param path An array of paths. * @param paths An array of paths.
* @param fallback The fallback classpath. * @param fallback The fallback classpath.
*/ */
public ClassPath(String[] paths, ClassPath fallback) { public ClassPath(String[] paths, ClassPath fallback) {
@ -530,7 +530,7 @@ public class ClassPath {
* Creates a new class path for the given path. See the class * Creates a new class path for the given path. See the class
* description for more information, which kind of paths are * description for more information, which kind of paths are
* supported. * supported.
* @param path An array of paths. * @param paths An array of paths.
*/ */
public ClassPath(String[] paths) { public ClassPath(String[] paths) {
initPath(paths); initPath(paths);
@ -971,7 +971,7 @@ public class ClassPath {
/** /**
* Get a list of all classes and packages in the given package. * Get a list of all classes and packages in the given package.
* @param package a dot-separated package name. * @param packageName a dot-separated package name.
* @return An enumeration with all class/subpackages in the given * @return An enumeration with all class/subpackages in the given
* package. If package doesn't denote a package it returns null. * package. If package doesn't denote a package it returns null.
*/ */

@ -37,6 +37,9 @@ import java.lang.Comparable;
* <dt>type</dt><dd>The field's {@link TypeSignature type signature} * <dt>type</dt><dd>The field's {@link TypeSignature type signature}
* in bytecode format.</dd> * in bytecode format.</dd>
* *
* <dt>signature</dt><dd>The field's {@link TypeSignature type signature}
* in bytecode format including template information.</dd>
*
* <dt>modifiers</dt><dd>The modifiers of the field like private, public etc. * <dt>modifiers</dt><dd>The modifiers of the field like private, public etc.
* These are created by or-ing the constants {@link Modifier#PUBLIC}, * These are created by or-ing the constants {@link Modifier#PUBLIC},
* {@link Modifier#PRIVATE}, {@link Modifier#PROTECTED}, * {@link Modifier#PRIVATE}, {@link Modifier#PROTECTED},
@ -65,7 +68,6 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
String typeSig; String typeSig;
Object constant; Object constant;
boolean syntheticFlag;
boolean deprecatedFlag; boolean deprecatedFlag;
/** /**
* The type signature that also contains template information. * The type signature that also contains template information.
@ -104,7 +106,7 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
int index = input.readUnsignedShort(); int index = input.readUnsignedShort();
constant = cp.getConstant(index); constant = cp.getConstant(index);
} else if (name.equals("Synthetic")) { } else if (name.equals("Synthetic")) {
syntheticFlag = true; modifier |= ACC_SYNTHETIC;
if (length != 0) if (length != 0)
throw new ClassFormatException throw new ClassFormatException
("Synthetic attribute has wrong length"); ("Synthetic attribute has wrong length");
@ -140,7 +142,7 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
else else
gcp.putConstant(constant); gcp.putConstant(constant);
} }
if (syntheticFlag) if (isSynthetic())
gcp.putUTF8("Synthetic"); gcp.putUTF8("Synthetic");
if (deprecatedFlag) if (deprecatedFlag)
gcp.putUTF8("Deprecated"); gcp.putUTF8("Deprecated");
@ -151,7 +153,7 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
int count = super.getAttributeCount(); int count = super.getAttributeCount();
if (constant != null) if (constant != null)
count++; count++;
if (syntheticFlag) if (isSynthetic())
count++; count++;
if (deprecatedFlag) if (deprecatedFlag)
count++; count++;
@ -173,7 +175,7 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
index = gcp.putConstant(constant); index = gcp.putConstant(constant);
output.writeShort(index); output.writeShort(index);
} }
if (syntheticFlag) { if (isSynthetic()) {
output.writeShort(gcp.putUTF8("Synthetic")); output.writeShort(gcp.putUTF8("Synthetic"));
output.writeInt(0); output.writeInt(0);
} }
@ -214,6 +216,16 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
return typeSig; return typeSig;
} }
/**
* Gets the type signature including template information of the field.
* <b>WARNING:</b> This field may disappear and merged into getType later.
* @return the type signature.
* @see TypeSignature
*/
public String getSignature() {
return signature != null ? signature : typeSig;
}
/** /**
* Gets the modifier of the field. * Gets the modifier of the field.
* @return the modifiers. * @return the modifiers.
@ -228,7 +240,7 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
* @return true if the field is synthetic. * @return true if the field is synthetic.
*/ */
public boolean isSynthetic() { public boolean isSynthetic() {
return syntheticFlag; return (modifier & ACC_SYNTHETIC) != 0;
} }
/** /**
@ -277,7 +289,10 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
} }
public void setSynthetic(boolean flag) { public void setSynthetic(boolean flag) {
syntheticFlag = flag; if (flag)
modifier |= ACC_SYNTHETIC;
else
modifier &= ~ACC_SYNTHETIC;
} }
public void setDeprecated(boolean flag) { public void setDeprecated(boolean flag) {

@ -37,6 +37,9 @@ import java.lang.Comparable;
* <dt>type</dt><dd>The method's {@link TypeSignature type signature} * <dt>type</dt><dd>The method's {@link TypeSignature type signature}
* in bytecode format.</dd> * in bytecode format.</dd>
* *
* <dt>signature</dt><dd>The method's {@link TypeSignature type signature}
* in bytecode format including template information.</dd>
*
* <dt>modifiers</dt><dd>The modifiers of the field like private, public etc. * <dt>modifiers</dt><dd>The modifiers of the field like private, public etc.
* These are created by or-ing the constants {@link Modifier#PUBLIC}, * These are created by or-ing the constants {@link Modifier#PUBLIC},
* {@link Modifier#PRIVATE}, {@link Modifier#PROTECTED}, * {@link Modifier#PRIVATE}, {@link Modifier#PROTECTED},
@ -69,7 +72,6 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
BasicBlocks basicblocks; BasicBlocks basicblocks;
String[] exceptions; String[] exceptions;
boolean syntheticFlag;
boolean deprecatedFlag; boolean deprecatedFlag;
/** /**
* The type signature that also contains template information. * The type signature that also contains template information.
@ -101,7 +103,7 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
throw new ClassFormatException throw new ClassFormatException
("Exceptions attribute has wrong length"); ("Exceptions attribute has wrong length");
} else if (name.equals("Synthetic")) { } else if (name.equals("Synthetic")) {
syntheticFlag = true; modifier |= ACC_SYNTHETIC;
if (length != 0) if (length != 0)
throw new ClassFormatException throw new ClassFormatException
("Synthetic attribute has wrong length"); ("Synthetic attribute has wrong length");
@ -141,7 +143,7 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
for (int i = 0; i < exceptions.length; i++) for (int i = 0; i < exceptions.length; i++)
gcp.putClassName(exceptions[i]); gcp.putClassName(exceptions[i]);
} }
if (syntheticFlag) if (isSynthetic())
gcp.putUTF8("Synthetic"); gcp.putUTF8("Synthetic");
if (deprecatedFlag) if (deprecatedFlag)
gcp.putUTF8("Deprecated"); gcp.putUTF8("Deprecated");
@ -154,7 +156,7 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
count++; count++;
if (exceptions != null) if (exceptions != null)
count++; count++;
if (syntheticFlag) if (isSynthetic())
count++; count++;
if (deprecatedFlag) if (deprecatedFlag)
count++; count++;
@ -177,7 +179,7 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
output.writeShort(gcp.putClassName(exceptions[i])); output.writeShort(gcp.putClassName(exceptions[i]));
} }
if (syntheticFlag) { if (isSynthetic()) {
output.writeShort(gcp.putUTF8("Synthetic")); output.writeShort(gcp.putUTF8("Synthetic"));
output.writeInt(0); output.writeInt(0);
} }
@ -213,6 +215,16 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
return typeSig; return typeSig;
} }
/**
* Gets the type signature including template information of the method.
* <b>WARNING:</b> This field may disappear and merged into getType later.
* @return the type signature.
* @see TypeSignature
*/
public String getSignature() {
return signature != null ? signature : typeSig;
}
public int getModifiers() { public int getModifiers() {
return modifier; return modifier;
} }
@ -226,7 +238,7 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
} }
public boolean isSynthetic() { public boolean isSynthetic() {
return syntheticFlag; return (modifier & ACC_SYNTHETIC) != 0;
} }
public boolean isDeprecated() { public boolean isDeprecated() {
@ -254,7 +266,10 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
} }
public void setSynthetic(boolean flag) { public void setSynthetic(boolean flag) {
syntheticFlag = flag; if (flag)
modifier |= ACC_SYNTHETIC;
else
modifier &= ~ACC_SYNTHETIC;
} }
public void setDeprecated(boolean flag) { public void setDeprecated(boolean flag) {

@ -28,7 +28,9 @@ import net.sf.jode.util.UnifyHash;
* Primitive types have a one letter type signature. Type signature * Primitive types have a one letter type signature. Type signature
* of classes contains the class name. Type signatures for arrays and * of classes contains the class name. Type signatures for arrays and
* methods are recursively build from the type signatures of their * methods are recursively build from the type signatures of their
* elements. <br> * elements. <br> Since java 5 there is a new class of type
* signatures supporting generics. These can be accessed with the
* getSignature methods of ClassInfo, MethodInfo and FieldInfo.
* *
* Here are a few examples: * Here are a few examples:
* <table><tr><th>type signature</th><th>Java type</th></tr> * <table><tr><th>type signature</th><th>Java type</th></tr>
@ -49,8 +51,17 @@ import net.sf.jode.util.UnifyHash;
* <tr><td><code>()I</code></td> * <tr><td><code>()I</code></td>
* <td> method without arguments * <td> method without arguments
* and <code>int</code> return type.</td></tr> * and <code>int</code> return type.</td></tr>
* <tr><td colspan="2"><code>&lt;E:Ljava/lang/Object;&gt;Ljava/lang/Object;Ljava/util/Collection&lt;TE;&gt;;</code></td>
* </tr><tr><td></td>
* <td> generic class over &lt;E extends Object&gt; extending
* Object and implementing Collections&lt;E&gt;</td></tr>
* <tr><td colspan="2"><code>&lt;T:Ljava/lang/Object;&gt;([TT;)[TT;</code></td>
* </tr><tr><td></td>
* <td> generic method over &lt;T extends Object&gt; taking an
* array of T as parameters and returning an array of T.</td></tr>
* </table> * </table>
* *
*
* @author Jochen Hoenicke * @author Jochen Hoenicke
*/ */
public class TypeSignature { public class TypeSignature {
@ -359,7 +370,7 @@ public class TypeSignature {
/** /**
* Checks whether a given type signature is a valid (not method) * Checks whether a given type signature is a valid (not method)
* type signature. Throws an exception otherwise. * type signature. Throws an exception otherwise.
* @param typeSig the type signature. * @param typesig the type signature.
* @exception NullPointerException if typeSig is null. * @exception NullPointerException if typeSig is null.
* @exception IllegalArgumentException if typeSig is not a valid * @exception IllegalArgumentException if typeSig is not a valid
* type signature or if it's a method type signature. * type signature or if it's a method type signature.
@ -380,7 +391,7 @@ public class TypeSignature {
/** /**
* Checks whether a given type signature is a valid method * Checks whether a given type signature is a valid method
* type signature. Throws an exception otherwise. * type signature. Throws an exception otherwise.
* @param typeSig the type signature. * @param typesig the type signature.
* @exception NullPointerException if typeSig is null. * @exception NullPointerException if typeSig is null.
* @exception IllegalArgumentException if typeSig is not a valid * @exception IllegalArgumentException if typeSig is not a valid
* method type signature. * method type signature.

@ -688,6 +688,10 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
* @return true, iff it shouldn't be written to the source code. * @return true, iff it shouldn't be written to the source code.
*/ */
public boolean skipWriting() { public boolean skipWriting() {
if (isSynthetic()
&& (minfo.getModifiers() & 0x0040 /*ACC_BRIDGE*/) != 0)
return true;
if (synth != null) { if (synth != null) {
// We don't need this class anymore (hopefully?) // We don't need this class anymore (hopefully?)
if (synth.getKind() == synth.GETCLASS) if (synth.getKind() == synth.GETCLASS)

@ -314,6 +314,8 @@ public final class InvokeOperator extends Operator
* inside the same base class as the caller class, null otherwise. * inside the same base class as the caller class, null otherwise.
*/ */
private ClassAnalyzer getClassAnalyzer(ClassInfo callee) { private ClassAnalyzer getClassAnalyzer(ClassInfo callee) {
if (callee == null)
return null;
if ((Options.options & if ((Options.options &
(Options.OPTION_ANON | Options.OPTION_INNER)) == 0) (Options.OPTION_ANON | Options.OPTION_INNER)) == 0)
return null; return null;

@ -820,7 +820,9 @@ public class FlowBlock {
/* The special start marker */ /* The special start marker */
continue; continue;
if (!pred.successors.containsKey(this)) if (!pred.successors.containsKey(this))
throw new InternalError("Inconsistency"); throw new InternalError
("Inconsistency: "+pred.getLabel()+" not in "
+this.getLabel()+".successors");
} }
StructuredBlock last = lastModified; StructuredBlock last = lastModified;
@ -829,41 +831,51 @@ public class FlowBlock {
|| last.outer instanceof FinallyBlock) || last.outer instanceof FinallyBlock)
last = last.outer; last = last.outer;
if (last.outer != null) if (last.outer != null)
throw new InternalError("Inconsistency"); throw new InternalError
("Inconsistency: last "+lastModified
+" surrounded by unexpected structure");
Iterator iter = successors.entrySet().iterator(); Iterator iter = successors.entrySet().iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next(); Map.Entry entry = (Map.Entry) iter.next();
FlowBlock dest = (FlowBlock) entry.getKey(); FlowBlock dest = (FlowBlock) entry.getKey();
if (dest.predecessors.contains(this) == (dest == END_OF_METHOD)) if (dest.predecessors.contains(this) == (dest == END_OF_METHOD))
throw new InternalError("Inconsistency"); throw new InternalError
("Inconsistency: dest "+dest.getLabel()
+" doesn't contain this predecessor");
Jump jumps = ((SuccessorInfo) entry.getValue()).jumps; Jump jumps = ((SuccessorInfo) entry.getValue()).jumps;
if (jumps == null) if (jumps == null)
throw new InternalError("Inconsistency"); throw new InternalError("Inconsistency: no jumps for "
+dest.getLabel());
for (; jumps != null; jumps = jumps.next) { for (; jumps != null; jumps = jumps.next) {
if (jumps.destination != dest) if (jumps.destination != dest)
throw new InternalError("Inconsistency"); throw new InternalError("Inconsistency:" +jumps
+ "doesn't point to "
+dest.getLabel());
if (jumps.prev == null if (jumps.prev == null
|| jumps.prev.flowBlock != this || jumps.prev.flowBlock != this
|| jumps.prev.jump != jumps) || jumps.prev.jump != jumps)
throw new InternalError("Inconsistency"); throw new InternalError("Inconsistency in" +jumps);
prev_loop: prev_loop:
for (StructuredBlock prev = jumps.prev; prev != block; for (StructuredBlock prev = jumps.prev; prev != block;
prev = prev.outer) { prev = prev.outer) {
if (prev.outer == null) if (prev.outer == null)
throw new RuntimeException("Inconsistency"); throw new InternalError("Inconsistency: " +prev
+" not in flowblock");
StructuredBlock[] blocks = prev.outer.getSubBlocks(); StructuredBlock[] blocks = prev.outer.getSubBlocks();
int i; int i;
for (i=0; i<blocks.length; i++) for (i=0; i<blocks.length; i++)
if (blocks[i] == prev) if (blocks[i] == prev)
continue prev_loop; continue prev_loop;
throw new InternalError("Inconsistency"); throw new InternalError("Inconsistency: " +prev
+" not in its outer block "
+prev.outer);
} }
} }
} }
@ -1357,8 +1369,35 @@ public class FlowBlock {
changed |= analyzeSwitch(start, end); changed |= analyzeSwitch(start, end);
} }
/* Do T1 analysis when there is a loop, but only if:
if (doT1(start, end)) { * - the loop has only one exit (plus returns)
* - or the successor block doesn't belong to the loop.
*
* The reason for the extra checks are loops like
*
* while (x)
* ...
* if (y)
* ...
* return
*
* which would otherwise be translated to:
*
* outer: do {
* do {
* if (!x) break outer;
* ...
* } while(!y)
* ...
* return
* } while(false)
*/
if (successors.containsKey(this)
&& (!successors.containsKey(nextByCodeOrder)
|| successors.size() == 2
|| (successors.size() == 3
&& successors.containsKey(END_OF_METHOD)))
&& doT1(start, end)) {
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_FLOW) != 0) if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_FLOW) != 0)
GlobalOptions.err.println("after T1: "+this); GlobalOptions.err.println("after T1: "+this);
@ -1443,7 +1482,7 @@ public class FlowBlock {
* The switch analyzation. This calls doSwitchT2 and doT1 on apropriate * The switch analyzation. This calls doSwitchT2 and doT1 on apropriate
* regions. Only blocks whose block number lies in the given block number * regions. Only blocks whose block number lies in the given block number
* range are considered and it is taken care of, that the switch * range are considered and it is taken care of, that the switch
* is never leaved. <p> * is never left. <p>
* The current flow block must contain the switch block as lastModified. * The current flow block must contain the switch block as lastModified.
* @param start the start of the block number range. * @param start the start of the block number range.
* @param end the end of the block number range. * @param end the end of the block number range.

Loading…
Cancel
Save