JVMTI 中间JNI系列功能,线程安全和故障排除技巧
JVMTI 中间JNI系列功能,线程安全和故障排除技巧
jni functions
在使用 JVMTI 的过程中,有一大系列的函数是在 JVMTI 的文档中
没有提及的,但在实际使用却是很实用的。
这就是 jni functions.
比如。在使用 SingleStep 函数时。
void JNICALL
SingleStep(jvmtiEnv *jvmti_env,
JNIEnv* jni_env,
jthread thread,
jmethodID method,
jlocation location)
我们就能够使用 jni_env 来调用 jni functions 中的一系列函数。
比如:
jclass mainClass = (*jni_env)->FindClass(jni_env, "Foo");
jfieldID fieldID = (*jni_env)->GetStaticFieldID(jni_env, mainClass, "x", "I");
jint fieldValue = (*jni_env)->GetStaticIntField(jni_env, mainClass, fieldID);
通过使用 jni functions 就能够获取 Foo 类中的静态整型变量的值。
另外在 jni functions 文档 中还有大量易用的
函数,都是在 JVMTI 文档中没有提及的。很实用。
事件回调函数的线程安全
在 JVMTI 中有一系列回调函数,当使用 SetEventNotificationMode
和 SetEventCallbacks
设置了某个事件的回调函数后。Java 虚拟机
在对应事件发生时,就会调用我们在 JVMTI 的 agent 中写的回调函数。
千万注意:多数回调函数须要保证线程安全
。
也就是说,我们写的回调函数要保证是可重入的。不然的话,一个线程运行时进入了回调函数,还没运行完这个回调函数时,可能会被切换
到还有一线程,而还有一线程也可能又一次进入这个回调函数,运行完之后,又切换回前一线程时,才继续运行上一个没有运行完的回调函数。
假设
你使用了全局变量,就要格外注意上述情况可能导致的数据不一致问题。
解决问题的最简单的办法就是使用 Raw Monitor。
在 Agent_OnLoad 函数中创建一个 Raw Monitor:
(*jvmti)->CreateRawMonitor(jvmti, "singelStep", &singleStepMonitorId);
然后。在回调函数的開始和结束时,使用这个 Raw Monitor 形成一个临界区,使得多个线程不能同一时候进入这个临界区:
void JNICALL
callbackSingleStep(
jvmtiEnv *jvmti,
JNIEnv* jni,
jthread thread,
jmethodID method,
jlocation location) {
(*jvmti)->RawMonitorEnter(jvmti, singleStepMonitorId);
...
(*jvmti)->RawMonitorExit(jvmti, singleStepMonitorId);
}
JVMTI agent 的调试
JVMTI 的 agent 假设出错,Java 虚拟机就会直接崩溃,同一时候生成一个 log,我们须要依据这个 log 推測 agent 中哪里出现了错误,比如:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000006f99f004, pid=6760, tid=8140
#
# JRE version: Java(TM) SE Runtime Environment (8.0_31-b13) (build 1.8.0_31-b13)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.31-b07 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# V [jvm.dll+0x12f004]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
#
...
Register to memory mapping:
RAX=0x0000000000000000 is an unknown value
RBX=0x000000005af15000 is a thread
RCX=0x000000005af15000 is a thread
RDX=0x00000000d707b160 is an oop
java.lang.NoSuchFieldError
- klass: 'java/lang/NoSuchFieldError'
RSP=0x000000005bcce510 is pointing into the stack for thread: 0x000000005af15000
RBP=0x000000005bcceb80 is pointing into the stack for thread: 0x000000005af15000
RSI={method} {0x0000000056b83b18} 'run' '()V' in 'TestCaset1000$1'
RDI=0x0000000000000000 is an unknown value
R8 =0x0000000000000000 is an unknown value
R9 =0x0000000000000b80 is an unknown value
R10=0xfefefefefefefeff is an unknown value
R11=0x8080808080808080 is an unknown value
R12=0x000000005af15000 is a thread
R13=0x000000005ae58030 is an unknown value
R14=0x0000000000000000 is an unknown value
R15=0x00000000024388e0 is an unknown value
Stack: [0x000000005bbd0000,0x000000005bcd0000], sp=0x000000005bcce510, free space=1017k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [jvm.dll+0x12f004]
C [TraceCapture.dll+0x5086] callbackSingleStep+0x466
V [jvm.dll+0x1a7389]
V [jvm.dll+0x1aa34c]
V [jvm.dll+0xa9c23]
C 0x00000000025afddd
...
当中 TraceCapture.dll 就是我写的 JVMTI agent,大概能够推測到是 callbackSingleStep+0x466
这个地方出一错误,异常
是 java.lang.NoSuchFieldError
。那么怎么找到这个位置呢?
这就涉及调试动态链接库文件了,调试的时候,在 callbackSingleStep 函数上加一个断点。调试时会停在这个断点上。
此时,首先查看 callbackSingleStep 的首地址,在 visual studio 2013 中把鼠标放在函数名上就能够显示出来,然后将这个地址添加
0x466,就找到了出错的位置的地址,再在 Call Stack 窗体中,右击 TraceCapture.dll 这一项进行反汇编。就进入了反汇编界面,
找到对应地址对应的函数语句就可以。
版权声明:本文博客原创文章,博客,未经同意,不得转载。
JVMTI 中间JNI系列功能,线程安全和故障排除技巧的更多相关文章
- 【FICO系列】SAP FI验证故障排除(调试)
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[FICO系列]SAP FI验证故障排除(调试) ...
- Java多线程系列--“JUC线程池”02之 线程池原理(一)
概要 在上一章"Java多线程系列--“JUC线程池”01之 线程池架构"中,我们了解了线程池的架构.线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析Th ...
- Java多线程系列--“JUC线程池”03之 线程池原理(二)
概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...
- linux高级编程基础系列:线程间通信
linux高级编程基础系列:线程间通信 转载:原文地址http://blog.163.com/jimking_2010/blog/static/1716015352013102510748824/ 线 ...
- Java多线程系列--“JUC线程池”06之 Callable和Future
概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...
- Java多线程系列--“JUC线程池”04之 线程池原理(三)
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--“基础篇”01之 基 ...
- Java多线程系列--“JUC线程池”05之 线程池原理(四)
概要 本章介绍线程池的拒绝策略.内容包括:拒绝策略介绍拒绝策略对比和示例 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3512947.html 拒绝策略 ...
- 死磕 java线程系列之线程池深入解析——普通任务执行流程
(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本. 注:线程池源码部分如无特殊说明均指ThreadPoolExecutor类. 简介 前面我们一起学习了Java中 ...
- Java并发编程系列-(2) 线程的并发工具类
2.线程的并发工具类 2.1 Fork-Join JDK 7中引入了fork-join框架,专门来解决计算密集型的任务.可以将一个大任务,拆分成若干个小任务,如下图所示: Fork-Join框架利用了 ...
随机推荐
- NVIDIA+关联2015写学校招收评论(嵌入式方向,上海)
我没有写很长一段时间Blog中的一个,在过去的几个月中还没有看到太多的生长技术,来来回回一直在做的事情,要毕业找工作,但发现并没有冷静下来,准备过.这不是让人觉得暂时补习班是凡人啊. 本科不试试.那你 ...
- flashfxp3.41中文版注册码:(适合最新版本)
推荐(尚未被封的 Realkey) FLASHFXPvACq2ssbvAAAAAC1W7cJKQTzmx77zmqJICvA7d3WnU tWNXdrp8YuERRFdIvXfOPbcpABkVix2 ...
- asp.net模板控件示例
原文:asp.net模板控件示例 模板控件允许将控件数据与其表示形式相分离,模板化控件不提供用户界面. 编写它则是为了实现一个命名容器以及包含属性和方法可由宿主页访问的类,MSDN是这样解释的. 下面 ...
- vb.net它SqlHelper制备及应用
上次文章中说到.对于一个项目来说.SqlHelper是一个非常重要的类. 在正在构造的机房收费系统中.有大量的操作数据库的操作. 现在.把反复的代码所有拿出来,就形成了SqlHelper类.这个Sql ...
- Android View系统解析(上)
- 复制(5)——事务复制中的发布者(Publisher)
发布者是所有被复制(replicated)的数据的集合.每个发布者可以有多个发布(publication),每个发布项包含多个项目(articles),但是这些发布必须处于一个单一的数据库中,而每个项 ...
- head first c<11>在根据网络编程
博文可以在一个大的网络通信实现,但是,一个人只能起到,我们能够给每个clientfork()子进程,实现诸多的服务. 方法: client连到server以后,server启动一个新创建的套接字对话. ...
- HDU 3065 病毒在继续 (AC自己主动机)
中国标题不解释 Sample Input 3 AA BB CC ooxxCC%dAAAoen....END Sample Output AA: 2 CC: 1 输出病毒出现的次数! #includ ...
- android 该项目的优化toast优化技巧
我们这样做的时候经常登录认证使用toast提示用户输入出现错误等..很多人都直接使用 Toast.makeText(LoginActivity.this, "请联系小区的物业管理" ...
- Smart Framework
Smart Framework:轻量级 Java Web 框架 发表于2年前(2013-09-01 08:39) 阅读(48569) | 评论(188) 544人收藏此文章, 我要收藏 赞83 阿 ...