Commit b988c367 authored by Yudi Zheng's avatar Yudi Zheng

Introduce shadow object programming model.

parent 6c574b54
......@@ -426,7 +426,7 @@ static void pack_class(JNIEnv * jni_env, buffer * buff, buffer * cmd_buff,
}
// pack null class id
pack_int(buff, NULL_NET_REF);
pack_long(buff, NULL_NET_REF);
}
static void buff_put_short(buffer * buff, size_t buff_pos, jshort to_put) {
......@@ -858,7 +858,7 @@ static void ot_tag_class(JNIEnv * jni_env, buffer * buff, size_t buff_pos,
get_net_reference(jni_env, jvmti_env, new_objs_buff, to_send);
// ... and put it on proper position
buff_put_int(buff, buff_pos, net_ref_get_class_id(net_ref));
buff_put_long(buff, buff_pos, net_ref);
}
static void ot_tag_buff(JNIEnv * jni_env, buffer * anl_buff, buffer * cmd_buff,
......
......@@ -18,5 +18,7 @@ static const jbyte MSG_CLASS_INFO = 4;
static const jbyte MSG_NEW_STRING = 5;
// sending registration for analysis method
static const jbyte MSG_REG_ANALYSIS = 6;
// sending thread info
static const jbyte MSG_THREAD_INFO = 7;
#endif /* _MESSAGETYPE_H */
......@@ -28,10 +28,12 @@ static volatile jint avail_class_id;
static const uint8_t OBJECT_ID_POS = 0;
static const uint8_t CLASS_ID_POS = 40;
static const uint8_t CLASS_INSTANCE_POS = 62;
static const uint8_t SPEC_POS = 63;
static const uint64_t OBJECT_ID_MASK = 0xFFFFFFFFFFL;
static const uint64_t CLASS_ID_MASK = 0x7FFFFF;
static const uint64_t CLASS_ID_MASK = 0x3FFFFF;
static const uint64_t CLASS_INSTANCE_MASK = 0x1;
static const uint64_t SPEC_MASK = 0x1;
// get bits from "from" with pattern "bit_mask" lowest bit starting on position
......@@ -74,6 +76,11 @@ inline unsigned char net_ref_get_spec(jlong net_ref) {
return get_bits(net_ref, SPEC_MASK, SPEC_POS);
}
inline unsigned char net_ref_get_class_instance_bit(jlong net_ref) {
return get_bits(net_ref, CLASS_INSTANCE_MASK, CLASS_INSTANCE_POS);
}
inline void net_ref_set_object_id(jlong * net_ref, jlong object_id) {
set_bits((uint64_t *)net_ref, object_id, OBJECT_ID_MASK, OBJECT_ID_POS);
......@@ -84,6 +91,11 @@ inline void net_ref_set_class_id(jlong * net_ref, jint class_id) {
set_bits((uint64_t *)net_ref, class_id, CLASS_ID_MASK, CLASS_ID_POS);
}
inline void net_ref_set_class_instance(jlong * net_ref, unsigned char cibit) {
set_bits((uint64_t *)net_ref, cibit, CLASS_INSTANCE_MASK, CLASS_INSTANCE_POS);
}
inline void net_ref_set_spec(jlong * net_ref, unsigned char spec) {
set_bits((uint64_t *)net_ref, spec, SPEC_MASK, SPEC_POS);
......@@ -114,7 +126,7 @@ static jclass _get_class_for_object(JNIEnv * jni_env, jobject obj) {
return (*jni_env)->GetObjectClass(jni_env, obj);
}
static int _object_is_class(jvmtiEnv * jvmti_env, jobject obj) {
static int _object_is_class(jvmtiEnv * jvmti_env, jobject obj) {
// TODO isn't there better way?
......@@ -129,15 +141,28 @@ static int _object_is_class(jvmtiEnv * jvmti_env, jobject obj) {
return TRUE;
}
static jclass DISL_JCLASS_JAVA_LANG_THREAD = NULL;
static jboolean _object_instanceof_thread(JNIEnv * jni_env, jobject obj) {
if (DISL_JCLASS_JAVA_LANG_THREAD == NULL ) {
DISL_JCLASS_JAVA_LANG_THREAD = (*jni_env)->NewGlobalRef(jni_env,
(*jni_env)->FindClass(jni_env, "java/lang/Thread"));
}
return (*jni_env)->IsInstanceOf(jni_env, obj, DISL_JCLASS_JAVA_LANG_THREAD);
}
// does not increment any counter - just sets the values
static jlong _set_net_reference(jvmtiEnv * jvmti_env, jobject obj,
jlong object_id, jint class_id, unsigned char spec) {
jlong object_id, jint class_id, unsigned char spec, unsigned char cbit) {
jlong net_ref = 0;
net_ref_set_object_id(&net_ref, object_id);
net_ref_set_class_id(&net_ref, class_id);
net_ref_set_spec(&net_ref, spec);
net_ref_set_class_instance(&net_ref, cbit);
jvmtiError error = (*jvmti_env)->SetTag(jvmti_env, obj, net_ref);
check_jvmti_error(jvmti_env, error, "Cannot set object tag");
......@@ -159,7 +184,7 @@ static void _pack_class_info(buffer * buff, jlong class_net_ref,
// msg id
pack_byte(buff, MSG_CLASS_INFO);
// class id
pack_int(buff, net_ref_get_class_id(class_net_ref));
pack_long(buff, class_net_ref);
// class signature
pack_string_utf8(buff, class_sig, strlen(class_sig));
// class generic string
......@@ -167,7 +192,26 @@ static void _pack_class_info(buffer * buff, jlong class_net_ref,
// class loader id
pack_long(buff, class_loader_net_ref);
// super class id
pack_int(buff, net_ref_get_class_id(super_class_net_ref));
pack_long(buff, super_class_net_ref);
}
static void _pack_thread_info(buffer * buff, jlong net_ref, const char *name,
jboolean isDaemon) {
// pack thread info message
// msg id
pack_byte(buff, MSG_THREAD_INFO);
// object id
pack_long(buff, net_ref);
// thread name
pack_string_utf8(buff, name, strlen(name));
// is daemon thread
pack_boolean(buff, isDaemon);
}
static jlong _set_net_reference_for_class(JNIEnv * jni_env,
......@@ -183,7 +227,7 @@ static jlong _set_net_reference_for_class(JNIEnv * jni_env,
// assign new net reference - set spec to 1 (binding send over network)
jlong net_ref = _set_net_reference(jvmti_env, klass,
avail_object_id, avail_class_id, 1);
avail_object_id, avail_class_id, 1, 1);
// increment object id counter
++avail_object_id;
......@@ -268,7 +312,17 @@ static jlong _set_net_reference_for_object(JNIEnv * jni_env,
// assign new net reference
jlong net_ref =
_set_net_reference(jvmti_env, obj, avail_object_id, class_id, 0);
_set_net_reference(jvmti_env, obj, avail_object_id, class_id, 0, 0);
if (_object_instanceof_thread(jni_env, obj)) {
jvmtiThreadInfo info_ptr;
jvmtiError error = (*jvmti_env)->GetThreadInfo(jvmti_env, obj,
&info_ptr);
check_jvmti_error(jvmti_env, error, "Cannot get thread info");
_pack_thread_info(buff, net_ref, info_ptr.name, info_ptr.is_daemon);
}
// increment object id counter
++avail_object_id;
......
......@@ -9,12 +9,9 @@ import java.util.List;
import ch.usi.dag.dislreserver.exception.DiSLREServerException;
import ch.usi.dag.dislreserver.msg.analyze.AnalysisResolver.AnalysisMethodHolder;
import ch.usi.dag.dislreserver.netreference.NetReference;
import ch.usi.dag.dislreserver.reflectiveinfo.ClassInfo;
import ch.usi.dag.dislreserver.reflectiveinfo.ClassInfoResolver;
import ch.usi.dag.dislreserver.reflectiveinfo.InvalidClass;
import ch.usi.dag.dislreserver.reqdispatch.RequestHandler;
import ch.usi.dag.dislreserver.stringcache.StringCache;
import ch.usi.dag.dislreserver.shadow.ShadowObject;
import ch.usi.dag.dislreserver.shadow.ShadowObjectTable;
public final class AnalysisHandler implements RequestHandler {
......@@ -172,54 +169,19 @@ public final class AnalysisHandler implements RequestHandler {
return Double.SIZE / Byte.SIZE;
}
if (argClass.equals (String.class)) {
long netRefNum = is.readLong ();
if (netRefNum != 0) {
// read string net reference and resolve it from cache
NetReference stringNR = new NetReference (netRefNum);
args.add (StringCache.resolve (stringNR.getObjectId ()));
} else {
// null handling
args.add (null);
}
if (ShadowObject.class.isAssignableFrom(argClass)) {
long net_ref = is.readLong();
return Long.SIZE / Byte.SIZE;
}
// read id only
// covers Object and NetReference classes
if (argClass.isAssignableFrom (NetReference.class)) {
long netRefNum = is.readLong ();
if (netRefNum != 0) {
// TODO: Lookup the reference
args.add (new NetReference (netRefNum));
// null handling
if (net_ref == 0) {
args.add(null);
} else {
// null handling
args.add (null);
args.add(ShadowObjectTable.get(net_ref));
}
return Long.SIZE / Byte.SIZE;
}
// return ClassInfo object
if (argClass.equals (ClassInfo.class)) {
int classNetRefNum = is.readInt ();
if (classNetRefNum != 0) {
args.add (ClassInfoResolver.getClass (classNetRefNum));
} else {
// null handling
args.add (null);
}
return Integer.SIZE / Byte.SIZE;
}
// return "invalid" class object
if (argClass.equals (Class.class)) {
args.add (InvalidClass.class);
return 0;
}
throw new DiSLREServerException (String.format (
"Unsupported data type %s in analysis method %s.%s",
argClass.getName (), analysisMethod.getDeclaringClass ().getName (),
......
......@@ -11,7 +11,7 @@ import java.util.Set;
import ch.usi.dag.dislreserver.exception.DiSLREServerException;
import ch.usi.dag.dislreserver.exception.DiSLREServerFatalException;
import ch.usi.dag.dislreserver.remoteanalysis.RemoteAnalysis;
import ch.usi.dag.dislreserver.stringcache.StringCache;
import ch.usi.dag.dislreserver.shadow.ShadowString;
public final class AnalysisResolver {
private static final String METHOD_DELIM = ".";
......@@ -51,10 +51,10 @@ public final class AnalysisResolver {
//
private static AnalysisMethodHolder resolveMethod (
final long methodStringId
ShadowString methodString
) throws DiSLREServerException {
try {
String methodStr = StringCache.resolve (methodStringId);
String methodStr = methodString.toString();
int classNameEnd = methodStr.lastIndexOf (METHOD_DELIM);
// without METHOD_DELIM
......@@ -135,9 +135,9 @@ public final class AnalysisResolver {
public static void registerMethodId (
final short methodId, final long methodStringId
final short methodId, ShadowString methodString
) throws DiSLREServerException {
methodMap.put(methodId, resolveMethod(methodStringId));
methodMap.put(methodId, resolveMethod(methodString));
}
......
......@@ -5,9 +5,11 @@ import java.io.DataOutputStream;
import java.io.IOException;
import ch.usi.dag.dislreserver.exception.DiSLREServerException;
import ch.usi.dag.dislreserver.netreference.NetReference;
import ch.usi.dag.dislreserver.reflectiveinfo.ClassInfoResolver;
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 {
......@@ -15,26 +17,25 @@ public class ClassInfoHandler implements RequestHandler {
throws DiSLREServerException {
try {
int classId = is.readInt();
long net_ref = is.readLong();
String classSignature = is.readUTF();
String classGenericStr = is.readUTF();
NetReference classLoaderNR = new NetReference(is.readLong());
int superClassId = is.readInt();
ClassInfoResolver.createHierarchy(classSignature, classGenericStr,
classLoaderNR, classId, superClassId);
}
catch (IOException e) {
ShadowObject classLoader = ShadowObjectTable.get(is.readLong());
ShadowClass superClass = (ShadowClass) ShadowObjectTable.get(is.readLong());
ShadowClassTable.newInstance(net_ref, superClass, classLoader,
classSignature, classGenericStr);
} catch (IOException e) {
throw new DiSLREServerException(e);
}
}
public void awaitProcessing() {
}
public void exit() {
}
}
......@@ -5,36 +5,37 @@ import java.io.DataOutputStream;
import java.io.IOException;
import ch.usi.dag.dislreserver.exception.DiSLREServerException;
import ch.usi.dag.dislreserver.netreference.NetReference;
import ch.usi.dag.dislreserver.reflectiveinfo.ClassInfoResolver;
import ch.usi.dag.dislreserver.reqdispatch.RequestHandler;
import ch.usi.dag.dislreserver.shadow.ShadowClassTable;
import ch.usi.dag.dislreserver.shadow.ShadowObject;
import ch.usi.dag.dislreserver.shadow.ShadowObjectTable;
public class NewClassHandler implements RequestHandler {
public void handle(DataInputStream is, DataOutputStream os, boolean debug)
throws DiSLREServerException {
try {
String className = is.readUTF();
NetReference classLoaderNR = new NetReference(is.readLong());
long oid = is.readLong();
ShadowObject classLoader = ShadowObjectTable.get(oid);
int classCodeLength = is.readInt();
byte[] classCode = new byte[classCodeLength];
is.readFully(classCode);
ClassInfoResolver.addNewClass(className, classLoaderNR, classCode);
}
catch (IOException e) {
ShadowClassTable.load(classLoader, className, classCode);
} catch (IOException e) {
throw new DiSLREServerException(e);
}
}
public void awaitProcessing() {
}
public void exit() {
}
}
......@@ -5,33 +5,33 @@ import java.io.DataOutputStream;
import java.io.IOException;
import ch.usi.dag.dislreserver.exception.DiSLREServerException;
import ch.usi.dag.dislreserver.netreference.NetReference;
import ch.usi.dag.dislreserver.reqdispatch.RequestHandler;
import ch.usi.dag.dislreserver.stringcache.StringCache;
import ch.usi.dag.dislreserver.shadow.ShadowObjectTable;
import ch.usi.dag.dislreserver.shadow.ShadowString;
public class NewStringHandler implements RequestHandler {
public void handle(DataInputStream is, DataOutputStream os, boolean debug)
throws DiSLREServerException {
try {
NetReference stringNR = new NetReference(is.readLong());
long net_ref = is.readLong();
String str = is.readUTF();
StringCache.register(stringNR.getObjectId(), str);
}
catch (IOException e) {
ShadowString sString = new ShadowString(net_ref, str);
ShadowObjectTable.register(sString);
} catch (IOException e) {
throw new DiSLREServerException(e);
}
}
public void awaitProcessing() {
}
public void exit() {
}
}
......@@ -7,37 +7,39 @@ import java.util.Set;
import ch.usi.dag.dislreserver.exception.DiSLREServerException;
import ch.usi.dag.dislreserver.msg.analyze.AnalysisResolver;
import ch.usi.dag.dislreserver.netreference.NetReference;
import ch.usi.dag.dislreserver.remoteanalysis.RemoteAnalysis;
import ch.usi.dag.dislreserver.reqdispatch.RequestHandler;
import ch.usi.dag.dislreserver.shadow.ShadowObject;
import ch.usi.dag.dislreserver.shadow.ShadowObjectTable;
public class ObjectFreeHandler implements RequestHandler {
public void handle(DataInputStream is, DataOutputStream os, boolean debug)
throws DiSLREServerException {
try {
NetReference netRef = new NetReference(is.readLong());
long net_ref = is.readLong();
ShadowObject obj = ShadowObjectTable.get(net_ref);
Set<RemoteAnalysis> raSet = AnalysisResolver.getAllAnalyses();
for(RemoteAnalysis ra : raSet) {
ra.objectFree(netRef);
for (RemoteAnalysis ra : raSet) {
ra.objectFree(obj);
}
// TODO ! re - free for special objects
ShadowObjectTable.freeShadowObject(net_ref, obj);
} catch (IOException e) {
throw new DiSLREServerException(e);
}
}
public void awaitProcessing() {
}
public void exit() {
}
}
......@@ -6,46 +6,40 @@ import java.io.IOException;
import ch.usi.dag.dislreserver.exception.DiSLREServerException;
import ch.usi.dag.dislreserver.msg.analyze.AnalysisResolver;
import ch.usi.dag.dislreserver.netreference.NetReference;
import ch.usi.dag.dislreserver.reqdispatch.RequestHandler;
import ch.usi.dag.dislreserver.stringcache.StringCache;
import ch.usi.dag.dislreserver.shadow.ShadowObjectTable;
import ch.usi.dag.dislreserver.shadow.ShadowString;
public final class RegAnalysisHandler implements RequestHandler {
public void handle (
final DataInputStream is, final DataOutputStream os, final boolean debug
) throws DiSLREServerException {
public void handle(final DataInputStream is, final DataOutputStream os,
final boolean debug) throws DiSLREServerException {
try {
final short methodId = is.readShort ();
NetReference methodStringNR = new NetReference (is.readLong ());
final short methodId = is.readShort();
final long methodStringID = is.readLong();
ShadowString methodString = (ShadowString) ShadowObjectTable.get(methodStringID);
// register method
AnalysisResolver.registerMethodId (
methodId, methodStringNR.getObjectId ()
);
AnalysisResolver.registerMethodId(methodId, methodString);
if (debug) {
System.out.printf (
"DiSL-RE: registered %s as analysis method %d\n",
StringCache.resolve (methodStringNR.getObjectId ()), methodId
);
System.out.printf(
"DiSL-RE: registered %s as analysis method %d\n",
methodString.toString(), methodId);
}
} catch (final IOException ioe) {
throw new DiSLREServerException (ioe);
throw new DiSLREServerException(ioe);
}
}
//
public void awaitProcessing () {
public void awaitProcessing() {
}
public void exit () {
public void exit() {
}
......
package ch.usi.dag.dislreserver.msg.threadinfo;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import ch.usi.dag.dislreserver.exception.DiSLREServerException;
import ch.usi.dag.dislreserver.reqdispatch.RequestHandler;
import ch.usi.dag.dislreserver.shadow.ShadowObjectTable;
import ch.usi.dag.dislreserver.shadow.ShadowThread;
public class ThreadInfoHandler implements RequestHandler {
public void handle(DataInputStream is, DataOutputStream os, boolean debug)
throws DiSLREServerException {
try {
long net_ref = is.readLong();
String name = is.readUTF();
boolean isDaemon = is.readBoolean();
ShadowThread sThread = new ShadowThread(net_ref, name, isDaemon);
ShadowObjectTable.register(sThread);
} catch (IOException e) {
throw new DiSLREServerException(e);
}
}
public void awaitProcessing() {
}
public void exit() {
}
}
package ch.usi.dag.dislreserver.netreference;
import ch.usi.dag.dislreserver.reflectiveinfo.ClassInfo;
import ch.usi.dag.dislreserver.reflectiveinfo.ClassInfoResolver;
public class NetReference {
final private long netRefeference;
final private long objectId;
final private int classId;
final private short spec;
public NetReference(long netReference) {
super();
this.netRefeference = netReference;
// initialize inner fields
this.objectId = net_ref_get_object_id(netReference);
this.classId = net_ref_get_class_id(netReference);
this.spec = net_ref_get_spec(netReference);
}
public long getNetRefeferenceRawNum() {
return netRefeference;
}
public long getObjectId() {
return objectId;
}
public int getClassId() {
return classId;
}
public short getSpec() {
return spec;
}
public ClassInfo getClassInfo() {
return ClassInfoResolver.getClass(classId);
}
// only object id considered
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (objectId ^ (objectId >>> 32));
return result;
}
// only object id considered
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
NetReference other = (NetReference) obj;
if (objectId != other.objectId)
return false;
return true;
}
// ************* special bit mask handling methods **********
// NOTE names of the methods are unusual for reason
// you can find almost identical methods in agent
// should be in sync with net_reference functions on the client
// format of net reference looks like this
// HIGHEST (1 bit spec, 23 bits class id, 40 bits object id)
// bit field not used because there is no guarantee of alignment
private final short OBJECT_ID_POS = 0;
private final short CLASS_ID_POS = 40;
private final short SPEC_POS = 63;
private final long OBJECT_ID_MASK = 0xFFFFFFFFFFL;
private final long CLASS_ID_MASK = 0x7FFFFFL;
private final long SPEC_MASK = 0x1L;
// get bits from "from" with pattern "bit_mask" lowest bit starting on position
// "low_start" (from 0)
private long get_bits(long from, long bit_mask, short low_start) {
// shift it
long bits_shifted = from >> low_start;
// mask it
return bits_shifted & bit_mask;
}
private long net_ref_get_object_id(long net_ref) {
return get_bits(net_ref, OBJECT_ID_MASK, OBJECT_ID_POS);
}
private int net_ref_get_class_id(long net_ref) {
return (int)get_bits(net_ref, CLASS_ID_MASK, CLASS_ID_POS);
}
private short net_ref_get_spec(long net_ref) {
return (short)get_bits(net_ref, SPEC_MASK, SPEC_POS);
}
}
package ch.usi.dag.dislreserver.reflectiveinfo;
import ch.usi.dag.dislreserver.netreference.NetReference;