我正在使用JVMTI代理进行动态字节码检测。我必须测试那些“热”的方法,即调用JIT编译器的方法。为此,我监听CompiledLoadEvent
,并在其回调函数中调用RetransformClasses
。这反过来对包含“hot”函数的类调用ClassFileLoadHook
,然后开始实际的检测。
目前,我正在安装我的类来生成一些线程。我也听线程启动和打印他们在我的代理。在类加载时使用简单的ClassFileLoadHook
(不使用RetransformClasses
),我的插装可以完美地工作并生成新的线程。当ClassFileLoadHook
在类加载时仪器时,我得到以下输出:
Running Thread: Signal Dispatcher, Priority: 9, context class loader:Not Null
Running Thread: main, Priority: 5, context class loader:Not Null
Running Thread: Thread-0, Priority: 5, context class loader:Not Null
Running Thread: Thread-1, Priority: 5, context class loader:Not Null
Running Thread: Thread-2, Priority: 5, context class loader:Not Null
Running Thread: Thread-3, Priority: 5, context class loader:Not Null
Running Thread: Thread-4, Priority: 5, context class loader:Not Null
Running Thread: Thread-6, Priority: 5, context class loader:Not Null
Running Thread: Thread-5, Priority: 5, context class loader:Not Null
Running Thread: Thread-7, Priority: 5, context class loader:Not Null
Running Thread: DestroyJavaVM, Priority: 5, context class loader:: NULL
当我通过调用retransformClasses
和ClassFileLoadHook
来检测类文件时,一切都很好,但是没有产生线程,因此没有进行有效的检测。VM即使执行原始代码也需要很长的时间。
[Loaded Test from __VM_RedefineClasses__]
[Loaded Test_Worker_main_0 from file:/home/saqib/workspace/test/bin]
我在运行时生成第二个类,它加载到VM,但我没有得到任何线程产生。
ClassFileLoadHook
在加载期间成功地重新转换了类,但在调用JIT时却不能正确地运行?retransformClasses
函数,并使用空的ClassFileLoadHook
回调,也需要大量时间而不会导致任何类型的错误。什么需要时间?static int x = 1;
void JNICALL
compiled_method_load(jvmtiEnv *jvmti, jmethodID method, jint code_size,
const void* code_addr, jint map_length, const jvmtiAddrLocationMap* map,
const void* compile_info) {
jvmtiError err;
jclass klass;
char* name = NULL;
char* signature = NULL;
char* generic_ptr = NULL;
err = (*jvmti)->RawMonitorEnter(jvmti, lock);
check_jvmti_error(jvmti, err, "raw monitor enter");
err = (*jvmti)->GetMethodName(jvmti, method, &name, &signature,
&generic_ptr);
check_jvmti_error(jvmti, err, "Get Method Name");
printf("\nCompiled method load event\n");
printf("Method name %s %s %s\n\n", name, signature,
generic_ptr == NULL ? "" : generic_ptr);
if (strstr(name, "main") != NULL && x == 1) {
x++;
err = (*jvmti)->GetMethodDeclaringClass(jvmti, method, &klass);
check_jvmti_error(jvmti, err, "Get Declaring Class");
err = (*jvmti)->RetransformClasses(jvmti, 1, &klass);
check_jvmti_error(jvmti, err, "Retransform class");
}
if (name != NULL) {
err = (*jvmti)->Deallocate(jvmti, (unsigned char*) name);
check_jvmti_error(jvmti, err, "deallocate name");
}
if (signature != NULL) {
err = (*jvmti)->Deallocate(jvmti, (unsigned char*) signature);
check_jvmti_error(jvmti, err, "deallocate signature");
}
if (generic_ptr != NULL) {
err = (*jvmti)->Deallocate(jvmti, (unsigned char*) generic_ptr);
check_jvmti_error(jvmti, err, "deallocate generic_ptr");
}
err = (*jvmti)->RawMonitorExit(jvmti, lock);
check_jvmti_error(jvmti, err, "raw monitor exit");
}
void JNICALL
Class_File_Load_Hook(jvmtiEnv *jvmti_env, JNIEnv* jni_env,
jclass class_being_redefined, jobject loader, const char* name,
jobject protection_domain, jint class_data_len,
const unsigned char* class_data, jint* new_class_data_len,
unsigned char** new_class_data) {
jvmtiError err;
unsigned char* jvmti_space = NULL;
if (strstr(name, "Test") != NULL && x == 2) {
char* args = "op";
javab_main(2, args, class_data, class_data_len);
err = (*jvmti_env)->Allocate(jvmti_env, (jlong)global_pos, &jvmti_space);
check_jvmti_error(jvmti_env, err, "Allocate new class Buffer.");
(void)memcpy((void*)jvmti_space, (void*)new_class_ptr, (int)global_pos);
*new_class_data_len = (jint)global_pos;
*new_class_data = jvmti_space;
if ( new_class_ptr != NULL ) {
(void)free((void*)new_class_ptr);
}
#if DEBUG
printf("Size of the class is: %d\n", class_data_len);
for (int i = 0; i < class_data_len; i += 4) {
if (i % 16 == 0)
printf("\n");
printf("%02x%02x %02x%02x ", new_class_data[i],
new_class_data[i + 1], new_class_data[i + 2],
new_class_data[i + 3]);
}
printf("\n");
system("javap -c -v Test_debug");
#endif
x++;
}
}
这里javab_main
返回检测的char*
数组,这是正确的。检测的数组存储在全局变量new_class_ptr
中,该变量被复制到new_class_data
中。为了调试检测的输出,我还将检测的类打印在一个名为Test_debug的文件中,并在其上调用javap
会产生所需的结果。
完整的代理文件如下所示:agent.c
for (int i = 0; i < s; i++)
for (int j = 0; j < s; j++) {
c2[i][j] = 0;
for (int k = 0; k < s; k++)
c2[i][j] += a[i][k] * b[k][j];
}
Thread[] threads = new Thread[NTHREADS];
for (int i = 0; i < NTHREADS ; i++) {
final int lb = i * SIZE/NTHREADS;
final int ub = (i+1) * SIZE/NTHREADS;
threads[i] = new Thread(new Runnable() {
public void run() {
for (int i = lb; i < ub; i++)
for (int j = 0; j < SIZE; j++) {
c2[i][j] = 0;
for (int k = 0; k < SIZE; k++)
c2[i][j] += a[i][k] * b[k][j];
}
}
});
threads[i].start();
}
// wait for completion
for (int i = 0; i < NTHREADS; i++) {
try {
threads[i].join();
} catch (InterruptedException ignore) {
}
}
openjdk version "1.8.0-internal-debug"
OpenJDK Runtime Environment (build 1.8.0-internal-debug-saqib_2016_12_26_10_52-b00)
OpenJDK 64-Bit Server VM (build 25.71-b00-debug, mixed mode)
我主要从评论中构造这个答案。还有一些谜团没有解开,但主要的问题已经解决了。字节码检测在我的情况下不会失败。实际上从来没有发生过。该理论认为,
执行函数的动态字节码检测在函数的后续调用中进行。如果一个函数只有一次调用,则在使用JVM中当前的hotswap技术执行时不能对其进行检测。
我试着给一个只有一个功能的类装乐器,即main。我试图在运行时调试它。这是主要的问题。为了检查这个参数的有效性,我尝试将我的代码放在另一个函数中,并在一个循环中从main调用它。它被仪器化了,一切都工作了。代理中没有什么需要改变的。
我对头衔认证有异议 这是我的密码 以下是传递的错误:Launchbrowser失败:titlevarification组织。testng。TestNgeException:无法将@Test注释的方法[TitlePrification]与[interface org.openqa.selenium.WebDriver]一起注入。有关本机依赖项注入的更多信息,请参阅https://testng.org
问题内容: 我读取了大约1000个文件名,其中一些文件以UTF8编码,而某些文件为CP1252。 我想将它们全部解码为Unicode,以便在脚本中进行进一步处理。有没有一种方法可以使源编码正确解码为Unicode? 例: 问题答案: 如果您的文件位于和中,则有一种简单的方法。 否则,有一个字符集检测库。 Python-检测字符集并转换为utf-8 https://pypi.python.org/p
一个“通过”测试但配置失败的示例。 失败的配置:@afterclass tearDown java.lang.assertionerror:java.lang.assertionerror:expected[true],但在)在org.testng.internal.MethodInvocationHelper.invokeMethodCommissioningTimeout(methodInvo
我昨天在Ubuntu上从1.5升级到了Android Studio 2.0。当我在Android Studio 2.0中进行单元测试时,它会显示终止的测试状态,即使所有测试都通过了。有时它只显示一些通过的测试。我很确定我的代码运行正常,测试正确,因为我在Android Studio 1.5上有相同的设置。 例如,我有22个测试。有时它显示所有22个测试都通过了,在下一次运行时,它显示22个测试中的
我正在尝试使用来生成网页、JS脚本和其他东西。看起来像这样: 在大多数情况下,它是有效的。Chrome成功从该服务器接收页面。 但是今天我注意到,如果有人足够快地发出大量请求,服务器就会开始拒绝连接。所以Chrome给了我这个: 在服务器端,我看不到我的try-catch中的任何错误。 我做错了什么?
我刚刚更新到Xcode 6 beta 6,我的代码有以下问题,以前我的代码可以正常工作 提醒子对象的类型为AnyObject?!当我试图将其向下转换为字符串时,它会崩溃,并显示“Swift dynamic cast failure”消息。println打印的值是:可选(嘿,它的测试!) 所以问题是如何正确地投射任何对象?!斯威夫特?