Commit dbbb33de authored by Yudi Zheng's avatar Yudi Zheng

Trigger loading of super classes before weaving sub class.

NOTE that the JNI environment will be NULL if sent during the primordial phase. In this phase, the current implementation is not able to change the loading order.
parent 7345a456
#ifndef _CLASSPARSER_H
#define _CLASSPARSER_H
#define CPCOUNT_OFFSET 8
#define CPTABLE_OFFSET 10
#define _CONSTANT_Class 7
#define _CONSTANT_Fieldref 9
#define _CONSTANT_Methodref 10
#define _CONSTANT_InterfaceMethodref 11
#define _CONSTANT_String 8
#define _CONSTANT_Integer 3
#define _CONSTANT_Float 4
#define _CONSTANT_Long 5
#define _CONSTANT_Double 6
#define _CONSTANT_NameAndType 12
#define _CONSTANT_Utf8 1
#define _CONSTANT_MethodType 16
#define _CONSTANT_MethodHandle 15
#define _CONSTANT_InvokeDynamic 20
// read short in big-endian bytes
static unsigned short read_short(const unsigned char * class_data,
unsigned int index) {
return (unsigned short) (((class_data[index] & 0xFF) << 8)
| ((class_data[index + 1] & 0xFF)));
}
// construct constant pool from raw bytes, and returns 10 + cpsize
// constant pool table 'cp' should be allocate before passing to this function
static int get_constant_pool(const unsigned char * class_data,
unsigned int * cp, unsigned short cpcount) {
// cp item index start from 1
unsigned int index = CPTABLE_OFFSET, count = 1;
// converted from ASM
while (count < cpcount) {
cp[count] = index;
switch (class_data[index]) {
case _CONSTANT_Fieldref:
case _CONSTANT_Methodref:
case _CONSTANT_InterfaceMethodref:
case _CONSTANT_Integer:
case _CONSTANT_Float:
case _CONSTANT_NameAndType:
case _CONSTANT_InvokeDynamic:
index += 5;
break;
case _CONSTANT_Long:
case _CONSTANT_Double:
index += 9;
count++;
break;
case _CONSTANT_Utf8:
index += 3 + read_short(class_data, index + 1);
break;
case _CONSTANT_MethodHandle:
index += 4;
break;
// case _CONSTANT_Class:
// case _CONSTANT_String:
// case _CONSTANT_MethodType:
default:
index += 3;
break;
}
count++;
}
return index;
}
#endif
......@@ -13,6 +13,7 @@
#include "jvmtihelper.h"
#include "comm.h"
#include "classparser.h"
#include "dislagent.h"
......@@ -373,6 +374,49 @@ static message instrument_class(const char * classname,
return result;
}
// load super class
static void load_super_class(JNIEnv* jni_env, const char* name,
const unsigned char* class_data) {
// allocate space for constant pool table
unsigned short cpcount = read_short(class_data, CPCOUNT_OFFSET);
unsigned int * cp = (unsigned int *) malloc(sizeof(int) * cpcount);
// construct constant pool and calculate offset of super class identifier
unsigned int class_off = get_constant_pool(class_data, cp, cpcount) + 4;
unsigned int class_idx = read_short(class_data, class_off);
if (class_idx == 0) {
// loading or redefining java.lang.Object, which has no super class
// free constant pool table
free((void *) cp);
cp = NULL;
return;
}
// super class name in constant pool, which is a "UTF-8"-type entry
unsigned int name_idx = read_short(class_data, cp[class_idx] + 1);
unsigned int name_off = cp[name_idx];
unsigned int name_len = read_short(class_data, name_off + 1);
char * name_src = ((char *) class_data) + name_off + 3;
// free constant pool table
free((void *) cp);
cp = NULL;
// copy super class name from constant pool
char * buf = (char *) malloc(name_len + 1);
strncpy(buf, name_src, name_len);
buf[name_len] = '\0';
// load super class
(*jni_env)->FindClass(jni_env, buf);
// free super class name
free((void *) buf);
buf = NULL;
}
// ******************* CLASS LOAD callback *******************
static void JNICALL jvmti_callback_class_file_load_hook( jvmtiEnv *jvmti_env,
......@@ -390,6 +434,10 @@ static void JNICALL jvmti_callback_class_file_load_hook( jvmtiEnv *jvmti_env,
}
#endif
if (jni_env != NULL) {
load_super_class(jni_env, name, class_data);
}
// ask the server to instrument
message instrclass = instrument_class(name, class_data, class_data_len);
......
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