kilim.analysis.AsmDetector Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kilim Show documentation
Show all versions of kilim Show documentation
Coroutines, continuations, fibers, actors and message passing for the JVM
// Copyright 2006 by sriram - offered under the terms of the MIT License
package kilim.analysis;
import java.util.LinkedList;
import java.io.IOException;
import java.util.HashMap;
import kilim.mirrors.Detector;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
/**
* This class is called by Detector to parse signatures of classes
* that may have verification errors. It uses asm to open the file instead
* of trying to classload it.
*/
public class AsmDetector {
static HashMap classCacheMap= new HashMap();
public static int getPausableStatus(String className, String methodName,
String desc, Detector detector)
{
try {
ClassCache classCache = classCacheMap.get(className);
if (classCache == null) {
ClassReader cr = new ClassReader(className);
ClassNode cn = new ClassNode();
cr.accept(cn, /*flags*/ 0);
classCache = cache(className, cn);
}
int status = classCache.getPausableStatus(methodName, desc);
if (status == Detector.METHOD_NOT_FOUND_OR_PAUSABLE) {
// check super classes
for (String superName: classCache.superClasses) {
status = detector.getPausableStatus(superName, methodName, desc);
if (status != Detector.METHOD_NOT_FOUND_OR_PAUSABLE)
break;
}
}
return status;
} catch (IOException ioe) {
System.err.println("***Error reading " + className + ": " + ioe.getMessage());
return Detector.METHOD_NOT_FOUND_OR_PAUSABLE;
}
}
private static ClassCache cache(String className, ClassNode cn) {
ClassCache classCache = new ClassCache();
classCache.className = className;
classCacheMap.put(className, classCache);
LOOP:
for (Object m: cn.methods) {
MethodNode mn = (MethodNode)m;
for (Object exception: mn.exceptions) {
if ("kilim/Pausable".equals(exception)) {
classCache.pausableMethods.add(mn.name + mn.desc);
continue LOOP;
}
}
classCache.otherMethods.add(mn.name + mn.desc);
}
classCache.addSuper(cn.superName);
for (Object interfaceName: cn.interfaces) {
classCache.addSuper((String)interfaceName);
}
// System.out.println(classCache);
return classCache;
}
public static void main(String[] args) {
AsmDetector.getPausableStatus(
"com/sleepycat/je/Database",
"putInternal",
"Lcom/sleepycat/je/Transaction;Lcom/sleepycat/je/DatabaseEntry;Lcom/sleepycat/je/DatabaseEntry;Lcom/sleepycat/je/dbi/PutMode;Lkilim/Fiber;)Lcom/sleepycat/je/OperationStatus;)V",
KilimContext.DEFAULT.detector);
}
static class ClassCache {
String className;
LinkedList pausableMethods = new LinkedList();
LinkedList otherMethods = new LinkedList();
LinkedList superClasses = new LinkedList();
public void addSuper(String superName) {
if (superName.equals("java/lang/Object")) return;
if (!superClasses.contains(superName)) {superClasses.add(superName);}
}
public int getPausableStatus(String methodName, String desc) {
String md = methodName + desc;
if (pausableMethods.contains(md)) {
return Detector.PAUSABLE_METHOD_FOUND;
} else if (otherMethods.contains(md)) {
return Detector.METHOD_NOT_PAUSABLE;
} else {
return Detector.METHOD_NOT_FOUND_OR_PAUSABLE;
}
}
@Override
public String toString() {
return className + "\nPausable Methods: " + pausableMethods + "\nOthers:" + otherMethods;
}
}
}