handle inner/outer/extra classes correctly

preserve package, if class preserved


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@808 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 25 years ago
parent b22d3c1e6b
commit 434e4c8e26
  1. 308
      jode/jode/obfuscator/ClassIdentifier.java

@ -66,8 +66,8 @@ public class ClassIdentifier extends Identifier {
if (wildcard.matches(fullName + identifiers[i].getName()) if (wildcard.matches(fullName + identifiers[i].getName())
|| wildcard.matches(fullName + identifiers[i].getName() || wildcard.matches(fullName + identifiers[i].getName()
+ "." +identifiers[i].getType())) { + "." +identifiers[i].getType())) {
if (GlobalOptions.verboseLevel > 1) if (GlobalOptions.verboseLevel > 0)
GlobalOptions.err.println("preserving "+identifiers[i]); GlobalOptions.err.println("Preserving "+identifiers[i]);
setPreserved(); setPreserved();
identifiers[i].setPreserved(); identifiers[i].setPreserved();
identifiers[i].setReachable(); identifiers[i].setReachable();
@ -94,18 +94,22 @@ public class ClassIdentifier extends Identifier {
public void reachableIdentifier(String name, String typeSig, public void reachableIdentifier(String name, String typeSig,
boolean isVirtual) { boolean isVirtual) {
// if (!isVirtual || (info.getModifiers() & Modifier.ABSTRACT) == 0) { boolean found = false;
for (int i=0; i< identifiers.length; i++) { for (int i=0; i< identifiers.length; i++) {
if (name.equals(identifiers[i].getName()) if (name.equals(identifiers[i].getName())
&& typeSig.equals(identifiers[i].getType())) && typeSig.equals(identifiers[i].getType())) {
identifiers[i].setReachable(); identifiers[i].setReachable();
found = true;
} }
// } }
if (!found) {
/*XXXXXXXX super reachableIdentifier */
} /*ELSE*/
if (isVirtual) { if (isVirtual) {
Enumeration enum = knownSubClasses.elements(); Enumeration enum = knownSubClasses.elements();
while (enum.hasMoreElements()) while (enum.hasMoreElements())
((ClassIdentifier)enum.nextElement()) ((ClassIdentifier)enum.nextElement())
.reachableIdentifier(name, typeSig, isVirtual); .reachableIdentifier(name, typeSig, false);
virtualReachables.addElement virtualReachables.addElement
(new String[] { name, typeSig }); (new String[] { name, typeSig });
} }
@ -136,10 +140,76 @@ public class ClassIdentifier extends Identifier {
if ((ident.info.getModifiers() if ((ident.info.getModifiers()
& (Modifier.TRANSIENT | Modifier.STATIC)) == 0) & (Modifier.TRANSIENT | Modifier.STATIC)) == 0)
identifiers[i].setPreserved(); identifiers[i].setPreserved();
/* XXX - only preserve them if writeObject not existent
* or if writeObject calls defaultWriteObject
*/
} }
} }
} }
/**
* Marks the package as preserved, too.
*/
protected void setSinglePreserved() {
pack.setPreserved();
}
public void setSingleReachable() {
super.setSingleReachable();
bundle.analyzeIdentifier(this);
}
public void analyzeSuperClasses(ClassInfo superclass) {
while (superclass != null) {
if (superclass.getName().equals("java.lang.Serializable"))
preserveSerializable();
ClassIdentifier superident
= bundle.getClassIdentifier(superclass.getName());
if (superident != null) {
superident.addSubClass(this);
} else {
// all virtual methods in superclass are reachable now!
MethodInfo[] topmethods = superclass.getMethods();
for (int i=0; i< topmethods.length; i++) {
int modif = topmethods[i].getModifiers();
if (((Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL)
& modif) == 0
&& !topmethods[i].getName().equals("<init>")) {
reachableIdentifier
(topmethods[i].getName(), topmethods[i].getType(),
true);
}
}
}
ClassInfo[] ifaces = superclass.getInterfaces();
for (int i=0; i < ifaces.length; i++)
initSuperClasses(ifaces[i]);
superclass = superclass.getSuperclass();
}
}
public void analyze() {
if (GlobalOptions.verboseLevel > 0)
GlobalOptions.err.println("Reachable: "+this);
ClassInfo[] ifaces = info.getInterfaces();
ifaceNames = new String[ifaces.length];
for (int i=0; i < ifaces.length; i++) {
ifaceNames[i] = ifaces[i].getName();
ClassIdentifier ifaceident
= bundle.getClassIdentifier(ifaceNames[i]);
analyzeSuperClasses(ifaces[i]);
}
if (info.getSuperclass() != null) {
superName = info.getSuperclass().getName();
ClassIdentifier superident
= bundle.getClassIdentifier(superName);
analyzeSuperClasses(info.getSuperclass());
}
}
public void initSuperClasses(ClassInfo superclass) { public void initSuperClasses(ClassInfo superclass) {
while (superclass != null) { while (superclass != null) {
if (superclass.getName().equals("java.lang.Serializable")) if (superclass.getName().equals("java.lang.Serializable"))
@ -172,9 +242,6 @@ public class ClassIdentifier extends Identifier {
if (((Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL) if (((Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL)
& modif) == 0 & modif) == 0
&& !topmethods[i].getName().equals("<init>")) { && !topmethods[i].getName().equals("<init>")) {
reachableIdentifier
(topmethods[i].getName(), topmethods[i].getType(),
true);
preserveIdentifier preserveIdentifier
(topmethods[i].getName(), topmethods[i].getType()); (topmethods[i].getName(), topmethods[i].getType());
} }
@ -187,16 +254,6 @@ public class ClassIdentifier extends Identifier {
} }
} }
public void setSingleReachable() {
super.setSingleReachable();
bundle.analyzeIdentifier(this);
}
public void analyze() {
if (GlobalOptions.verboseLevel > 0)
GlobalOptions.err.println("Reachable: "+this);
}
public void initClass() { public void initClass() {
info.loadInfo(info.FULLINFO); info.loadInfo(info.FULLINFO);
@ -250,9 +307,6 @@ public class ClassIdentifier extends Identifier {
ifaceNames[i] = ifaces[i].getName(); ifaceNames[i] = ifaces[i].getName();
ClassIdentifier ifaceident ClassIdentifier ifaceident
= bundle.getClassIdentifier(ifaceNames[i]); = bundle.getClassIdentifier(ifaceNames[i]);
if (ifaceident != null) {
ifaceident.addSubClass(this);
}
initSuperClasses(ifaces[i]); initSuperClasses(ifaces[i]);
} }
@ -260,11 +314,32 @@ public class ClassIdentifier extends Identifier {
superName = info.getSuperclass().getName(); superName = info.getSuperclass().getName();
ClassIdentifier superident ClassIdentifier superident
= bundle.getClassIdentifier(superName); = bundle.getClassIdentifier(superName);
if (superident != null) {
superident.addSubClass(this);
}
initSuperClasses(info.getSuperclass()); initSuperClasses(info.getSuperclass());
} }
// load inner classes
InnerClassInfo[] innerClasses = info.getInnerClasses();
InnerClassInfo[] outerClasses = info.getOuterClasses();
InnerClassInfo[] extraClasses = info.getExtraClasses();
if (outerClasses != null) {
for (int i=0; i < outerClasses.length; i++) {
if (outerClasses[i].outer != null) {
bundle.getClassIdentifier(outerClasses[i].outer);
}
}
}
if (innerClasses != null) {
for (int i=0; i < innerClasses.length; i++) {
bundle.getClassIdentifier(innerClasses[i].inner);
}
}
if (extraClasses != null) {
for (int i=0; i < extraClasses.length; i++) {
bundle.getClassIdentifier(extraClasses[i].inner);
if (extraClasses[i].outer != null)
bundle.getClassIdentifier(extraClasses[i].outer);
}
}
} }
public void buildTable(int renameRule) { public void buildTable(int renameRule) {
@ -330,61 +405,147 @@ public class ClassIdentifier extends Identifier {
public void transformInnerClasses() { public void transformInnerClasses() {
InnerClassInfo[] innerClasses = info.getInnerClasses(); InnerClassInfo[] innerClasses = info.getInnerClasses();
if (innerClasses == null) InnerClassInfo[] outerClasses = info.getOuterClasses();
InnerClassInfo[] extraClasses = info.getExtraClasses();
if (innerClasses == null && outerClasses == null
&& extraClasses == null)
return; return;
int newInnerCount; int newInnerCount, newOuterCount, newExtraCount;
if (Obfuscator.shouldStrip) { if (Obfuscator.shouldStrip) {
newInnerCount = 0; newInnerCount = newOuterCount = newExtraCount = 0;
for (int i=0; i < innerClasses.length; i++) { if (outerClasses != null) {
ClassIdentifier innerIdent for (int i=0; i < outerClasses.length; i++) {
= bundle.getClassIdentifier(innerClasses[i].inner); if (outerClasses[i].outer != null) {
if (innerIdent == null || innerIdent.isReachable()) ClassIdentifier outerIdent
= bundle.getClassIdentifier(outerClasses[i].outer);
if (outerIdent == null || outerIdent.isReachable())
newOuterCount++;
} else
newOuterCount++;
}
}
if (innerClasses != null) {
for (int i=0; i < innerClasses.length; i++) {
ClassIdentifier innerIdent
= bundle.getClassIdentifier(innerClasses[i].inner);
if (innerIdent == null || innerIdent.isReachable())
newInnerCount++; newInnerCount++;
}
} }
} else if (extraClasses != null) {
newInnerCount = innerClasses.length; for (int i=0; i < extraClasses.length; i++) {
ClassIdentifier outerIdent = extraClasses[i].outer != null
InnerClassInfo[] newInners = new InnerClassInfo[newInnerCount]; ? bundle.getClassIdentifier(extraClasses[i].outer)
newInnerCount = 0; : null;
ClassIdentifier innerIdent
= bundle.getClassIdentifier(extraClasses[i].inner);
if ((outerIdent == null || outerIdent.isReachable())
&& (innerIdent == null || innerIdent.isReachable()))
newExtraCount++;
}
}
} else {
newInnerCount = innerClasses != null ? innerClasses.length : 0;
newOuterCount = outerClasses != null ? outerClasses.length : 0;
newExtraCount = extraClasses != null ? extraClasses.length : 0;
}
for (int i=0; i<innerClasses.length; i++) { InnerClassInfo[] newInners = newInnerCount > 0
ClassIdentifier innerIdent ? new InnerClassInfo[newInnerCount] : null;
= bundle.getClassIdentifier(innerClasses[i].inner); InnerClassInfo[] newOuters = newOuterCount > 0
if (innerIdent != null && !innerIdent.isReachable()) ? new InnerClassInfo[newOuterCount] : null;
continue; InnerClassInfo[] newExtras = newExtraCount > 0
? new InnerClassInfo[newExtraCount] : null;
String inner, outer, name; if (newInners != null) {
if (innerIdent == null) { int pos = 0;
inner = innerClasses[i].inner; for (int i=0; i<innerClasses.length; i++) {
} else { ClassIdentifier innerIdent
inner = innerIdent.getAlias(); = bundle.getClassIdentifier(innerClasses[i].inner);
} if (innerIdent != null && !innerIdent.isReachable())
if (innerClasses[i].outer == null) { continue;
outer = null;
} else { String inner, outer, name;
ClassIdentifier outerIdent if (innerIdent == null) {
= bundle.getClassIdentifier(innerClasses[i].outer); inner = innerClasses[i].inner;
if (outerIdent != null) {
if (Obfuscator.shouldStrip && !outerIdent.isReachable())
outer = null;
else
outer = outerIdent.getAlias();
} else { } else {
outer = innerClasses[i].outer; inner = innerIdent.getFullAlias();
} }
outer = getFullAlias();
if (innerClasses[i].name == null)
/* This is an anonymous class */
name = null;
else if (outer != null && inner.startsWith(outer+"$"))
name = inner.substring(outer.length()+1);
else
name = inner;
newInners[pos++] = new InnerClassInfo
(inner, outer, name, innerClasses[i].modifiers);
}
}
if (newOuters != null) {
int pos = 0;
String lastClass = getFullAlias();
for (int i=0; i<outerClasses.length; i++) {
ClassIdentifier outerIdent = outerClasses[i].outer != null
? bundle.getClassIdentifier(outerClasses[i].outer)
: null;
if (outerIdent != null && !outerIdent.isReachable())
continue;
String inner = lastClass;
String outer = outerIdent == null
? outerClasses[i].outer : outerIdent.getFullAlias();
String name;
lastClass = outer;
if (outerClasses[i].name == null)
/* This is an anonymous class */
name = null;
else if (outer != null && inner.startsWith(outer+"$"))
name = inner.substring(outer.length()+1);
else
name = inner.substring(inner.lastIndexOf('.')+1);
newOuters[pos++] = new InnerClassInfo
(inner, outer, name, outerClasses[i].modifiers);
}
}
if (newExtras != null) {
int pos = 0;
for (int i=0; i<extraClasses.length; i++) {
ClassIdentifier outerIdent = extraClasses[i].outer != null
? bundle.getClassIdentifier(extraClasses[i].outer)
: null;
ClassIdentifier innerIdent
= bundle.getClassIdentifier(extraClasses[i].inner);
if (innerIdent != null && !innerIdent.isReachable())
continue;
if (outerIdent != null && !outerIdent.isReachable())
continue;
String inner = innerIdent == null
? extraClasses[i].inner : innerIdent.getFullAlias();
String outer = outerIdent == null
? extraClasses[i].outer : outerIdent.getFullAlias();
String name;
if (extraClasses[i].name == null)
/* This is an anonymous class */
name = null;
else if (outer != null && inner.startsWith(outer+"$"))
name = inner.substring(outer.length()+1);
else
name = inner;
newExtras[pos++] = new InnerClassInfo
(inner, outer, name, extraClasses[i].modifiers);
} }
if (innerClasses[i].name == null)
/* This is an anonymous class */
name = null;
else if (outer != null && inner.startsWith(outer+"$"))
name = inner.substring(outer.length()+1);
else
name = inner;
newInners[newInnerCount++] = new InnerClassInfo
(inner, outer, name, innerClasses[i].modifiers);
} }
info.setInnerClasses(newInners); info.setInnerClasses(newInners);
info.setOuterClasses(newOuters);
info.setExtraClasses(newExtras);
} }
public void doTransformations() { public void doTransformations() {
@ -456,7 +617,10 @@ public class ClassIdentifier extends Identifier {
* @return the full qualified alias, excluding trailing dot. * @return the full qualified alias, excluding trailing dot.
*/ */
public String getFullAlias() { public String getFullAlias() {
return pack.getFullAlias() + getAlias(); if (pack.parent == null)
return getAlias();
else
return pack.getFullAlias() + "." + getAlias();
} }
public String getName() { public String getName() {

Loading…
Cancel
Save