Skip to content

Commit

Permalink
Good news: now i know test doesn't work on linux
Browse files Browse the repository at this point in the history
  • Loading branch information
acrylic-style committed Jul 20, 2021
1 parent 0071827 commit ef14b3d
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 26 deletions.
27 changes: 24 additions & 3 deletions src/main/c/common-tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ extern "C" {
static jclass ClassAssertionError;
static jclass ClassClass;
static jclass ClassMethod;
static jclass ClassThread;
static jclass ClassIllegalArgumentException;
static jclass ClassNoSuchElementException;
static jclass ClassBoolean;
Expand All @@ -34,6 +35,21 @@ static jvmtiEnv * GetJvmti(JavaVM *jvm) {

static std::list<jobject> classLoadHooks; // NOLINT(cert-err58-cpp)

static jthread GetCurrentThread(JNIEnv *env) {
jmethodID mid = env->GetStaticMethodID(ClassThread, "currentThread", "()Ljava/lang/Thread;");
return env->CallStaticObjectMethod(ClassThread, mid);
}

static bool EnsureStackDoesNotContain(jvmtiEnv *jvmti, JNIEnv *env, jmethodID mid) {
jvmtiFrameInfo frames[25];
jint count;
jvmti->GetStackTrace(GetCurrentThread(env), 0, 25, frames, &count);
for (int i = 0; i < count; ++i) {
if (frames[i].method == mid) return false;
}
return true;
}

static void classLoadHook(jvmtiEnv *jvmti_env,
JNIEnv* jni_env,
jclass class_being_redefined,
Expand All @@ -44,14 +60,18 @@ static void classLoadHook(jvmtiEnv *jvmti_env,
const unsigned char* class_data,
jint* new_class_data_len,
unsigned char** new_class_data) {
if (name == nullptr) return;
jmethodID mid = jni_env->GetMethodID(ClassClassLoadHook, "transform", "(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/Class;Ljava/security/ProtectionDomain;[B)[B");
jbyteArray arr = jni_env->NewByteArray(class_data_len);
jni_env->SetByteArrayRegion(arr, 0, class_data_len, (jbyte*) class_data);
jstring j_name = jni_env->NewStringUTF(name);
for (const jobject &item : classLoadHooks) {
jobject obj = jni_env->CallObjectMethod(item, mid, loader, j_name, class_being_redefined, protection_domain, arr);
if (obj != nullptr) {
arr = reinterpret_cast<jbyteArray>(obj);
jmethodID mid2 = jni_env->GetMethodID(jni_env->GetObjectClass(item), "transform", "(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/Class;Ljava/security/ProtectionDomain;[B)[B");
if (EnsureStackDoesNotContain(jvmti_env, jni_env, mid2)) {
jobject obj = jni_env->CallObjectMethod(item, mid, loader, j_name, class_being_redefined, protection_domain, arr);
if (obj != nullptr) {
arr = reinterpret_cast<jbyteArray>(obj);
}
}
}
*new_class_data_len = jni_env->GetArrayLength(arr);
Expand All @@ -64,6 +84,7 @@ static void InitTools(JNIEnv *env) {
ClassAssertionError = reinterpret_cast<jclass>(env->NewGlobalRef(env->FindClass("java/lang/AssertionError")));
ClassClass = reinterpret_cast<jclass>(env->NewGlobalRef(env->FindClass("java/lang/Class")));
ClassMethod = reinterpret_cast<jclass>(env->NewGlobalRef(env->FindClass("java/lang/reflect/Method")));
ClassThread = reinterpret_cast<jclass>(env->NewGlobalRef(env->FindClass("java/lang/Thread")));
ClassIllegalArgumentException = reinterpret_cast<jclass>(env->NewGlobalRef(env->FindClass("java/lang/IllegalArgumentException")));
ClassNoSuchElementException = reinterpret_cast<jclass>(env->NewGlobalRef(env->FindClass("java/util/NoSuchElementException")));
ClassBoolean = reinterpret_cast<jclass>(env->NewGlobalRef(env->FindClass("java/lang/Boolean")));
Expand Down
Binary file modified src/main/resources/libnativeutil.dll
Binary file not shown.
Binary file modified src/main/resources/libnativeutil.so
Binary file not shown.
19 changes: 0 additions & 19 deletions src/test/java/net/blueberrymc/native_util/NativeUtilTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,25 +83,6 @@ public void testGetObjectSize() {
assert size == 16L : size;
}

@Test
public void testClassLoadHook() {
AtomicBoolean hasLoaded = new AtomicBoolean();
NativeUtil.registerClassLoadHook((loader, className, classBeingRedefined, protectionDomain, buf) -> {
System.out.println("Loading class " + className);
if (className.equals("net/blueberrymc/native_util/TestClass")) {
hasLoaded.set(true);
}
return null;
});
new TestClass();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
assert hasLoaded.get() : "net/blueberrymc/native_util/TestClass was not loaded";
}

private static class A {
@SuppressWarnings("unused")
public int getSomething() {
Expand Down
4 changes: 0 additions & 4 deletions src/test/java/net/blueberrymc/native_util/TestClass.java

This file was deleted.

0 comments on commit ef14b3d

Please sign in to comment.