Commit fa64d56a authored by Lubomir Bulej's avatar Lubomir Bulej

ClassInfoLoader: move shadow class creation to ShadowClassTable, leave only IO.

ShadowClassTable: preprocess data from ClassInfoLoader before calling newInstance().
ShadowClassTable: simplify the implementation of newInstance(), extract class creation into __createShadowClass().
ShadowObject: make getNetRef() package private.
ShadowObject: use get() on the JAVA_LANG_CLASS atomic reference.
ObjectShadowClass: use ASM Type instead of String with class signature.
parent 34ed6ce3
......@@ -6,41 +6,38 @@ import java.io.IOException;
import ch.usi.dag.dislreserver.DiSLREServerException;
import ch.usi.dag.dislreserver.reqdispatch.RequestHandler;
import ch.usi.dag.dislreserver.shadow.ShadowClass;
import ch.usi.dag.dislreserver.shadow.ShadowClassTable;
import ch.usi.dag.dislreserver.shadow.ShadowObject;
import ch.usi.dag.dislreserver.shadow.ShadowObjectTable;
public class ClassInfoHandler implements RequestHandler {
public final class ClassInfoHandler implements RequestHandler {
@Override
public void handle (
DataInputStream is, DataOutputStream os, boolean debug
final DataInputStream is, final DataOutputStream os,
final boolean debug
) throws DiSLREServerException {
try {
long net_ref = is.readLong ();
String classSignature = is.readUTF ();
String classGenericStr = is.readUTF ();
ShadowObject classLoader = ShadowObjectTable.get (is.readLong ());
ShadowClass superClass = (ShadowClass) ShadowObjectTable.get (
is.readLong ()
);
ShadowClassTable.newInstance (
net_ref, superClass, classLoader, classSignature,
classGenericStr, debug
final long netReference = is.readLong ();
final String typeDescriptor = is.readUTF ();
final String classGenericStr = is.readUTF ();
final long classLoaderNetReference = is.readLong ();
final long superclassNetReference = is.readLong ();
ShadowClassTable.registerClass (
netReference, typeDescriptor, classGenericStr,
classLoaderNetReference, superclassNetReference
);
} catch (IOException e) {
} catch (final IOException e) {
throw new DiSLREServerException (e);
}
}
@Override
public void exit () {
// do nothing
}
}
......@@ -7,6 +7,7 @@ import java.util.List;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.InnerClassNode;
......@@ -29,7 +30,7 @@ class ObjectShadowClass extends ShadowClass {
ObjectShadowClass (
final long netReference, final String classSignature,
final long netReference, final Type type,
final ShadowObject classLoader, final ShadowClass superClass,
final byte [] classCode
) {
......@@ -38,7 +39,7 @@ class ObjectShadowClass extends ShadowClass {
__superClass = superClass;
if (classCode == null || classCode.length == 0) {
throw new DiSLREServerFatalException (
"Creating class info for "+ classSignature + " with no code provided"
"Creating class info for "+ type + " with no code provided"
);
}
......
package ch.usi.dag.dislreserver.shadow;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import org.objectweb.asm.Type;
......@@ -11,24 +12,35 @@ public class ShadowClassTable {
private static final int INITIAL_TABLE_SIZE = 10000;
final static ShadowObject BOOTSTRAP_CLASSLOADER;
//
static ShadowClass JAVA_LANG_CLASS;
static final ShadowObject BOOTSTRAP_CLASSLOADER;
private static ConcurrentHashMap <ShadowObject, ConcurrentHashMap <String, byte []>> classLoaderMap;
static final AtomicReference <ShadowClass> JAVA_LANG_CLASS;
private static final Type __JAVA_LANG_CLASS_TYPE__;
//
private static ConcurrentHashMap <Integer, ShadowClass> shadowClasses;
private static ConcurrentHashMap <ShadowObject, ConcurrentHashMap <String, byte []>> classLoaderMap;
//
static {
BOOTSTRAP_CLASSLOADER = new ShadowObject (0, null);
JAVA_LANG_CLASS = null;
JAVA_LANG_CLASS = new AtomicReference <> ();
__JAVA_LANG_CLASS_TYPE__ = Type.getType (Class.class);
classLoaderMap = new ConcurrentHashMap <> (INITIAL_TABLE_SIZE);
shadowClasses = new ConcurrentHashMap <> (INITIAL_TABLE_SIZE);
classLoaderMap.put (BOOTSTRAP_CLASSLOADER, new ConcurrentHashMap <String, byte []> ());
classLoaderMap = new ConcurrentHashMap <> (INITIAL_TABLE_SIZE);
BOOTSTRAP_CLASSLOADER = new ShadowObject (0, null);
classLoaderMap.put (BOOTSTRAP_CLASSLOADER, new ConcurrentHashMap <> ());
}
//
public static void load (
ShadowObject loader, final String className, final byte [] classCode, final boolean debug
......@@ -55,76 +67,110 @@ public class ShadowClassTable {
}
public static ShadowClass newInstance (
final long net_ref, final ShadowClass superClass, ShadowObject loader,
final String classSignature, final String classGenericStr, final boolean debug
static ShadowClass newInstance (
final long classNetReference, final Type type,
final String classGenericStr, final ShadowObject classLoader,
final ShadowClass superClass
) {
if (!NetReferenceHelper.isClassInstance (net_ref)) {
throw new DiSLREServerFatalException ("Unknown class instance");
if (!NetReferenceHelper.isClassInstance (classNetReference)) {
throw new DiSLREServerFatalException (String.format (
"Not a Class<> instance: 0x%x", classNetReference
));
}
ShadowClass klass = null;
final Type t = Type.getType (classSignature);
//
if (t.getSort () == Type.ARRAY) {
// TODO unknown array component type
klass = new ArrayShadowClass (net_ref, loader, superClass, null, t);
final int classId = NetReferenceHelper.getClassId (classNetReference);
ShadowClass result = shadowClasses.get (classId);
if (result == null) {
result = __createShadowClass (
classNetReference, type, superClass, classLoader
);
final ShadowClass previous = shadowClasses.putIfAbsent (classId, result);
if (previous == null) {
ShadowObjectTable.register (result);
} else if (t.getSort () == Type.OBJECT) {
ConcurrentHashMap <String, byte []> classNameMap;
} else if (previous.equals (result)) {
result = previous;
if (loader == null) {
} else {
// Someone else just created a class with the same class id,
// but for some reason the classes are not equal.
throw new DiSLREServerFatalException (String.format (
"different shadow classes (%s) for id (0x%x)",
type, classId
));
}
}
//
if (JAVA_LANG_CLASS.get () == null && __JAVA_LANG_CLASS_TYPE__.equals (type)) {
JAVA_LANG_CLASS.compareAndSet (null, result);
}
return result;
}
private static ShadowClass __createShadowClass (
final long netReference, final Type type,
final ShadowClass superClass, ShadowObject classLoader
) {
//
// Assumes that the sort of primitive types is lexicographically
// before the sort of arrays and subsequently objects.
//
if (type.getSort () < Type.ARRAY) {
// Primitive type should return null as classloader.
return new PrimitiveShadowClass (netReference, classLoader, type);
} else if (type.getSort () == Type.ARRAY) {
// TODO unknown array component type
// Array types have the same class loader as their component type.
return new ArrayShadowClass (netReference, classLoader, superClass, null, type);
} else if (type.getSort () == Type.OBJECT) {
if (classLoader == null) {
// bootstrap loader
loader = BOOTSTRAP_CLASSLOADER;
classLoader = BOOTSTRAP_CLASSLOADER;
}
classNameMap = classLoaderMap.get (loader);
final ConcurrentHashMap <String, byte []> classNameMap = classLoaderMap.get (classLoader);
if (classNameMap == null) {
throw new DiSLREServerFatalException ("Unknown class loader");
}
final byte [] classCode = classNameMap.get (t.getClassName ());
final byte [] classCode = classNameMap.get (type.getClassName ());
if (classCode == null) {
throw new DiSLREServerFatalException (
"Class "+ t.getClassName () + " has not been loaded"
"Class "+ type.getClassName () + " has not been loaded"
);
}
klass = new ObjectShadowClass (
net_ref, classSignature, loader, superClass, classCode
return new ObjectShadowClass (
netReference, type, classLoader, superClass, classCode
);
} else {
klass = new PrimitiveShadowClass (net_ref, loader, t);
throw new DiSLREServerFatalException ("unpextected sort of type: "+ type.getSort ());
}
final int classID = NetReferenceHelper.getClassId (net_ref);
final ShadowClass exist = shadowClasses.putIfAbsent (classID, klass);
if (exist == null) {
ShadowObjectTable.register (klass);
} else if (!exist.equals (klass)) {
throw new DiSLREServerFatalException ("Duplicated class ID");
}
if (JAVA_LANG_CLASS == null && "Ljava/lang/Class;".equals (classSignature)) {
JAVA_LANG_CLASS = klass;
}
return klass;
}
public static ShadowClass get (final int classID) {
if (classID == 0) {
public static ShadowClass get (final int classId) {
if (classId == 0) {
// reserved ID for java/lang/Class
return null;
}
final ShadowClass klass = shadowClasses.get (classID);
final ShadowClass klass = shadowClasses.get (classId);
if (klass == null) {
throw new DiSLREServerFatalException ("Unknown class instance");
throw new DiSLREServerFatalException (String.format (
"Unknown Class<> instance: 0x%x", classId
));
}
return klass;
......@@ -133,12 +179,24 @@ public class ShadowClassTable {
public static void freeShadowObject (final ShadowObject obj) {
if (NetReferenceHelper.isClassInstance (obj.getNetRef ())) {
final int classID = NetReferenceHelper.getClassId (obj.getNetRef ());
shadowClasses.remove (classID);
final int classId = NetReferenceHelper.getClassId (obj.getNetRef ());
shadowClasses.remove (classId);
} else if (classLoaderMap.keySet ().contains (obj)) {
} else if (classLoaderMap.containsKey (obj)) {
classLoaderMap.remove (obj);
}
}
public static void registerClass (
final long netReference, final String typeDescriptor,
final String classGenericStr, final long classLoaderNetReference,
final long superclassNetReference
) {
final Type type = Type.getType (typeDescriptor);
final ShadowObject classLoader = ShadowObjectTable.get (classLoaderNetReference);
final ShadowClass superClass = (ShadowClass) ShadowObjectTable.get (superclassNetReference);
newInstance (netReference, type, classGenericStr, classLoader, superClass);
}
}
......@@ -10,6 +10,11 @@ public class ShadowObject implements Formattable {
private final long __netReference;
/**
* The {@link ShadowClass} of this object. If {@code null}, then this object
* represents an instance of the {@link Class} class, or (in a singular
* case) the bootstrap class loader.
*/
private final ShadowClass __shadowClass;
private final AtomicReference <Object> __shadowState;
......@@ -24,8 +29,7 @@ public class ShadowObject implements Formattable {
//
@Deprecated
public final long getNetRef () {
final long getNetRef () {
return __netReference;
}
......@@ -44,11 +48,10 @@ public class ShadowObject implements Formattable {
throw new NullPointerException ();
}
return ShadowClassTable.JAVA_LANG_CLASS;
return ShadowClassTable.JAVA_LANG_CLASS.get ();
}
}
//
public final Object getState () {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment