Re: ASM4 / Java 7
Eliot Moss <[email protected]>
| Newsgroups | gmane.comp.java.objectweb.asm |
|---|---|
| Message-ID | <[email protected]> |
Jeremy -- I think you're talking about the need to compute the common superclass of two classes. I wrote some code to do that. It uses a static table to remember some facts about classes that our rewriting agent sees, and so will have what it needs to know about the superclasses. It does not need to *load* the classes, only to have seen them come by the transformer, and superclasses are always seen before the subclasses. Most of the code of the class I attach is relevant; the visitMethod method may not be for you. Maybe there are more elegant ways to do this, but it seems to work for the cases we have run so far. Best wishes -- Eliot Moss
ETPreprocessor.java
(text/x-java, 4 KB)
package classReWriter;
import org.objectweb.asm.*;
import org.objectweb.asm.commons.*;
import java.io.*;
import java.util.*;
import java.lang.System;
public class ETPreprocessor extends ClassAdapter {
public static final Map<String,String> superclassOf = new HashMap<String,String>();
public static final Map<String,Set<String>> superinterfacesOf =
new HashMap<String,Set<String>>();
public static final Set<String> interfaces = new HashSet<String>();
public static final Map<String,Integer> depthOf = new HashMap<String,Integer>();
public ETPreprocessor (ClassVisitor cv) {
super(cv);
}
@Override
public void visit (int version, int access, String name, String signature,
String supername, String[] interfaces) {
super.visit(version, access, name, signature, supername, interfaces);
if (name.equals("java/lang/Object")) {
return;
}
if ((access & Opcodes.ACC_INTERFACE) != 0) {
this.interfaces.add(name);
}
superclassOf.put(name, supername);
Set<String> intfs = new HashSet<String>(2 * interfaces.length);
superinterfacesOf.put(name, intfs);
for (String intf : interfaces) {
intfs.add(intf);
this.interfaces.add(intf);
}
depthOf.put(name, computeDepth(name));
}
@Override
public MethodVisitor visitMethod (int access, String name, String desc,
String signature, String[] exceptions) {
MethodVisitor writer = cv.visitMethod(access, name, desc, signature, exceptions);
return new JSRInlinerAdapter(writer, access, name, desc, signature, exceptions);
}
public static String commonSuperclass (String c1, String c2) {
List<String> supers1 = computeSupers(c1);
List<String> supers2 = computeSupers(c2);
if (supers1.contains(c2)) {
return c1;
}
if (supers2.contains(c1)) {
return c2;
}
if (interfaces.contains(c1) || interfaces.contains(c2)) {
return "java/lang/Object";
}
while (true) {
c1 = superclassOf.get(c1);
if (c1 == null) {
return "java/lang/Object";
}
if (supers2.contains(c1)) {
return c1;
}
}
}
private static int computeDepth (String c) {
if (c == null || c.equals("java/lang/Object")) {
return 0;
} else if (depthOf.containsKey(c)) {
return depthOf.get(c);
}
String sc = superclassOf.get(c);
int depth = computeDepth(sc) + 1;
Set<String> intfs = superinterfacesOf.get(c);
if (intfs != null) {
for (String intf : intfs) {
int newDepth = computeDepth(intf) + 1;
if (newDepth > depth) {
depth = newDepth;
}
}
}
depthOf.put(c, depth);
return depth;
}
private static List<String> computeSupers (String c) {
List<String> temp = new ArrayList<String>();
List<Integer> depth = new ArrayList<Integer>();
List<String> queue = new LinkedList<String>();
Set<String> found = new HashSet<String>();
temp.add(c);
depth.add(computeDepth(c));
queue.add(c);
found.add(c);
while (!queue.isEmpty()) {
String next = queue.remove(0);
String sc = superclassOf.get(next);
if (sc == null) {
sc = "java/lang/Object";
}
if (!found.contains(sc)) {
temp.add(sc);
depth.add(computeDepth(sc));
queue.add(sc);
found.add(sc);
}
Set<String> intfs = superinterfacesOf.get(next);
if (intfs != null) {
for (String intf : intfs) {
if (!found.contains(intf)) {
temp.add(intf);
depth.add(computeDepth(intf));
queue.add(intf);
found.add(intf);
}
}
}
}
List<String> result = new ArrayList<String>(temp.size());
int maxDepth = depth.get(0);
for (int d = maxDepth; d >= 0; --d) {
for (int i = depth.size(); --i >= 0; ) {
if (depth.get(i) == d) {
result.add(temp.get(i));
}
}
}
return result;
}
}
// Local Variables:
// mode:Java
// c-basic-offset:2
// indent-tabs-mode:nil
// End:
message-footer.txt
(text/plain, 238 B)
-- You receive this message as a subscriber of the [email protected] mailing list. To unsubscribe: mailto:[email protected] For general help: mailto:[email protected]?subject=help OW2 mailing lists service home page: http://www.ow2.org/wws