- 浏览: 110350 次
- 性别:
- 来自: 深圳
最新评论
-
xemp45:
好久木有更新了咧,wei 哥说你还是在这边办公额?
mybatis/Mysql常用命令 -
beck5859509:
wangxuehui 写道文章写的不错,希望多写写哈哈,一起学 ...
跟我一起学习C(指针篇1) -
wangxuehui:
文章写的不错,希望多写写
跟我一起学习C(指针篇1) -
beck5859509:
wangxuehui 写道即&p的值0x7fff654 ...
跟我一起学习C(指针篇1) -
wangxuehui:
即&p的值0x7fff65485a00修改为abc h ...
跟我一起学习C(指针篇1)
/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"于公司jvm智能分析平台的思考
引子
在讲述主题之前,先看一下之前遇到的几个问题
1、问题一
2、问题二
3、问题三
url1
url2
url3
目前公司缺少一个jvm智能分析平台,在遇到一些比较难定位的问题时,往往只能查看日志,或者临时添加日志,但也会带来一些麻烦,比如日志量过大,进程重启问题不必现等,又或者只能反复jstack进行问题猜测,但效果也不理想。
jvm智能分析平台的特点。
1、动态加载,目标程序无需重启
2、字节码编程、性能得到保障
3、web平台化操作
3、目标方法的入参、异常、返回结果的分析
4、目标方法内部每一行代码的hao时的分析
5、指定java实例数统计及size分析
3、与第三方jar进行隔离,代码无污染
4、对线程栈做快照对线程
demo展示
冰山一角
可行性
已和运维组勇哥沟通,并无相关的平台,只是简单的组件的监控
相关技术
/java/jni/jvmti/bytecode/c/c++
1、统计指定的java实例数,并可以统计每个实例的大小(size)
2、查找最高耗时的方法(小型程序)
3、拉取git代码进行web在线调试
4、采集到与JVM 有关的大量信息,例如内存、线程、JVM 崩溃等
5、对线程栈做快照
6、Java Agent受jvm本身的影响
总结
Native Agent因为工作原理的不同,导致其与Java Agent相比,拥有明显的优势,具体总结如下:
1. 获取JVM运行时的性能参数。
2. 获取JVM线程方法调用栈信息
3. 不受JVM的运行状态影响。
4. 开销更少
visitAnnotationDefault?
( visitAnnotation | visitParameterAnnotation | visitAttribute )*
( visitCode
( visitTryCatchBlock | visitLabel | visitFrame | visitXxxInsn |
visitLocalVariable | visitLineNumber )*
visitMaxs )?
visitEnd
Btrace (Byte Trace)是sun推出的一款Java 动态、安全追踪(监控)工具,可以在不停机的情况下监控系统运行情况,并且做到最少的侵入,占用最少的系统资源。。BTrace在使用上做了很多限制,如不能创建对象、不能使用数组、不能抛出或捕获异常、不能使用循环、不能使用synchronized关键字、脚本的属性和方法都必须使用static修饰等,具体限制条件可参考用户手册。根据官方声明,不当地使用BTrace可能导致JVM崩溃,如BTrace使用错误的.class文件,所以,可以先在本地验证BTrace脚本的正确性再使用
https://blog.csdn.net/coslay/article/details/43113029
https://www.cnblogs.com/163yun/p/10078137.html
asm:
0: aload_0
首先第一个0代表虚指令中的行号(后面会应到,确切说应该是方法的body部分第几个字节),每个方法从0开始顺序递增,但是可以跳跃,跳跃的原因在于一些指令还会接操作的内容,这些操作的内容可能来自常量池,也可以标志是第几个slot的本地变量,因此需要占用一定的空间。
aload_0指令是将“第1个”slot所在的本地变量推到栈顶,并且这个本地变量是引用类型的,相关的指令有:aload_[0-3](范围是:0x2a ~ 0x2d)。如果超过4个,则会使用“aload + 本地变量的slot位置”来完成(此时会多占用1个字节来存放),前者是通过具体的几个指令直接完成。
许多地方会解释为第1个引用类型的本地变量,但胖哥是一个逻辑怪,认为这句话有问题,并不是第1个引用变量,普通变量如果在它之前,它也不是第1个了,此时本身就是第1个本地变量,更确切地说是第一个slot所在位置的本地变量。
注意:
常量池的存放内容
存放所有的方法名
field名
方法签名(方法参数+返回值)
类型名
class文件中的常量值
常量池的前四部分可以称作是符号引用(即只有一些名称,但没有实际的地址,在运行期进行类的加载过后,会为这些东西分配实际的内存,到时候符号引用就会转化为直接引用,就能被JVM用了)
常量池的组成:符号引用、常量(这个常量包含我们代码中定义的常量,eg、字符串常量,也包括class文件中的常量,eg.SourceFile)。
主版本号的对应(eg.50对应jdk6,51对应jdk7),查看《深入理解java虚拟机(第二版)》P167
Stack:操作数栈的深度(这个值就是类加载阶段为操作数栈分配的深度)
Locals:局部变量的分配空间(单位是slot,不是个数),对于double和long这两个64bit的,需要两个slot,对于其他<=32bit的,只需要一个slot
Args_size:方法参数的个数,包括方法参数、this(this只针对实例方法,static方法不会自动添加this)
inc()方法:我详细注释了该方法的执行过程,这也就是JVM执行一个方法的基本流程(基于栈)
ClassReader.java
// visits the class declaration
classVisitor.visit(readInt(items[1] - 7), access, name, signature,
superClass, interfaces);
// visits the source and debug info
if ((flags & SKIP_DEBUG) == 0
&& (sourceFile != null || sourceDebug != null)) {
classVisitor.visitSource(sourceFile, sourceDebug);
}
// visits the module info and associated attributes
if (module != 0) {
readModule(classVisitor, context, module,
moduleMainClass, packages);
}
// visits the outer class
if (enclosingOwner != null) {
classVisitor.visitOuterClass(enclosingOwner, enclosingName,
enclosingDesc);
}
// visits the class annotations and type annotations
if (anns != 0) {
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true,
classVisitor.visitAnnotation(readUTF8(v, c), true));
}
}
if (ianns != 0) {
for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true,
classVisitor.visitAnnotation(readUTF8(v, c), false));
}
}
if (tanns != 0) {
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true,
classVisitor.visitTypeAnnotation(context.typeRef,
context.typePath, readUTF8(v, c), true));
}
}
if (itanns != 0) {
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true,
classVisitor.visitTypeAnnotation(context.typeRef,
context.typePath, readUTF8(v, c), false));
}
}
// visits the attributes
while (attributes != null) {
Attribute attr = attributes.next;
attributes.next = null;
classVisitor.visitAttribute(attributes);
attributes = attr;
}
// visits the inner classes
if (innerClasses != 0) {
int v = innerClasses + 2;
for (int i = readUnsignedShort(innerClasses); i > 0; --i) {
classVisitor.visitInnerClass(readClass(v, c),
readClass(v + 2, c), readUTF8(v + 4, c),
readUnsignedShort(v + 6));
v += 8;
}
}
// visits the fields and methods
u = header + 10 + 2 * interfaces.length;
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
u = readField(classVisitor, context, u);
}
u += 2;
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
u = readMethod(classVisitor, context, u);
}
// visits the end of the class
classVisitor.visitEnd();
引子
在正式讲述本文主题前,先看一下之前项目中遇到的几个问题
问题一
问题现象:18年12月底的时候线上有一台手机在 18:00~21:00之间频繁连接和断开连接
分析步骤:
1、客户端同事初步分析手机日志,发现有断开异常,看调用堆栈是业务代码抛出
image.png
2、联想到后台主动关闭连接时,不会写入mqtt 消息,所以输入流stream读不到数据属于正常现象。
另外问题发生时的日志已经被清除,只能查看客户端的其它日志,幸运的是当时有网络包可以分析
3、查看网络请求终于发现一些端倪:
image.png
image.png
客户端先是连接101.132.150.36,同时后台139.196.100.216断开客户端连接(18:00:53前的连接),18:01分客户端又继续连接139.196.100.216,形成循环连接的现象。
重点查看连接connack的返回结果,找到了突破口。
image.png
4、第二个红框值为3,代表需要重新注册。因个别手机在多用户场景会出现连接切换重连的情况,后台发现token不匹配就会进行重连,客户端已经针对此情况修复。
问题二
问题现象:5月初收到ups-receiver线程池任务队列阻塞的监控报警
分析步骤:
1、查看错误日志,并没有找到相应的线索,也没有异常的日志。
2、因为当天凌晨12点半发现,临时重启解决问题。
3、对比内外部的receiver,单独拆分了回执线程池处理,并发布上线观察。
4、果然第二天问题还是出现,打印jstack进行分析。
5、问题得到确认,回执写入mq时的线程被阻塞,联系中间件同事进行处理,问题得以解决。
image.png
其它烧脑问题
http://km.vivo.xyz/pages/viewpage.action?pageId=28500755
http://km.vivo.xyz/pages/viewpage.action?pageId=16279250
http://km.vivo.xyz/pages/viewpage.action?pageId=14488732
当前痛点:
梳理以上问题时都存在一个共同特点,业务在遇到一些比较难定位的问题时,往往只能查看日志,或者临时添加日志,但这也会带来一些麻烦,比如日志量过大,
进程重启问题不必现,需要临时发布版本(可能引入其它风险)等,或者只能反复jstack进行问题猜测,但效果都不理想。当然针对不同层次需求场景,有对应
的工具,比如内存占用过多,得不到释放,可以dump出文件,但是分析此文件也并不容易,有一定的成本。还有类似jconsole等工具,但已有的这些工具并不能
满足高级的应用场景,比如动态查看方法的入参/返回结果/某个成员变量的值就可以很快定位出问题。
解决方案:
一个比较好的解决方案是建设一个公司级的JVM智能分析平台 --- 开发人员可以根据不同场景输入参数快速定位问题,提前监测,并协助智能分析问题发生的根因。
jvm智能分析平台具备以下特点。
1、动态加载,目标程序无需重启
2、字节码编程、性能得到保障
3、web平台化操作
4、对目标方法的入参、异常、返回结果的分析
5、对目标方法内部代码的耗时的分析
6、对指定java实例数统计及size分析
7、与第三方jar进行隔离,代码无污染
8、对线程堆栈智能分析可能的问题原因
冰山一角
jdk1.5以后,jdk整合了一套有关虚拟机的JVMTI接口,可以供使用者调用,JVMTI的功能非常丰富,包含了访问虚拟机中线程/内存/堆/栈/类/方法/变量的方法。
开发者可以灵活使用这些特性,开发出很多高级功能,比如上述提到的功能,不过这些接口是C/C++的,实现起来有一定的难度。以下例举两个例子。
例一:
比如下面展示了一个比较有趣的例子---通过java类名查找进程中对应实例的数量,具本如下。
1、java端的统计调用功能由一个本地方法实现,通过jni的方式嵌入jvm中,具体实现通过c++代码去实现
image.png
2、监控程序启动时开启jvm统计对象数的功能
image.png
3、使用jvmit的方法迭代对象size及实例个数
image.png
4、最终结果,已之前java代码预期一致
image.png
除了通过jvmti实现上述功能(实现成本偏高),jdk还提供了instrument技术,可通过字节码转换进行实现相同的功能,并且功能更强大,
除了实现监测,还可以动态添加新的功能:)
例二:
这里例举给目标方法动态添加try/catch及一个局部变量int i = 20的例子,当然也可以增加耗时统计
1、Student类中最初的say方法
image.png
编译后Student的say方法字节码:
image.png
2、对目标方法进行添加字节码(部分代码)
image.png
3、编译后say方法的字节码
image.png
查看上图汇编后的字节码文件,istore_1已经将栈顶的int值20保存到了局部变量中,并且增加了try/catch的异常捕获
总结:字节码编程方式同样可以动态实现目标程序的变更,但底层也通过jvmti进行实现的,但是通过字节码简单化了jvmti的开发工作量,当然为了更好的理解
是有必要同时掌握jvmti指令及字节码指定的。以上只是字节码编程的冰山一角,这里不展开介绍了。
以下是 jvm智能分析平台架构图
image.png
该系统后期还可以衍生其它更强大的功能:比如通过web端拉取git代码在线调试线上环境(支付宝目前已有类似的功能)
成本:
关于系统人力评估(正式加两个外包-前端和后端各一人)
收益 :
1、智能分析系统,提前发现疑难、隐藏较深的问题,减少线上问题造成的损失。
2、节省定位问题成本,现在项目越来越多,系统逻辑也越来越复杂,通过该系统快速锁定问题原因。
引子
在讲述主题之前,先看一下之前遇到的几个问题
1、问题一
2、问题二
3、问题三
url1
url2
url3
目前公司缺少一个jvm智能分析平台,在遇到一些比较难定位的问题时,往往只能查看日志,或者临时添加日志,但也会带来一些麻烦,比如日志量过大,进程重启问题不必现等,又或者只能反复jstack进行问题猜测,但效果也不理想。
jvm智能分析平台的特点。
1、动态加载,目标程序无需重启
2、字节码编程、性能得到保障
3、web平台化操作
3、目标方法的入参、异常、返回结果的分析
4、目标方法内部每一行代码的hao时的分析
5、指定java实例数统计及size分析
3、与第三方jar进行隔离,代码无污染
4、对线程栈做快照对线程
demo展示
冰山一角
可行性
已和运维组勇哥沟通,并无相关的平台,只是简单的组件的监控
相关技术
/java/jni/jvmti/bytecode/c/c++
1、统计指定的java实例数,并可以统计每个实例的大小(size)
2、查找最高耗时的方法(小型程序)
3、拉取git代码进行web在线调试
4、采集到与JVM 有关的大量信息,例如内存、线程、JVM 崩溃等
5、对线程栈做快照
6、Java Agent受jvm本身的影响
总结
Native Agent因为工作原理的不同,导致其与Java Agent相比,拥有明显的优势,具体总结如下:
1. 获取JVM运行时的性能参数。
2. 获取JVM线程方法调用栈信息
3. 不受JVM的运行状态影响。
4. 开销更少
visitAnnotationDefault?
( visitAnnotation | visitParameterAnnotation | visitAttribute )*
( visitCode
( visitTryCatchBlock | visitLabel | visitFrame | visitXxxInsn |
visitLocalVariable | visitLineNumber )*
visitMaxs )?
visitEnd
Btrace (Byte Trace)是sun推出的一款Java 动态、安全追踪(监控)工具,可以在不停机的情况下监控系统运行情况,并且做到最少的侵入,占用最少的系统资源。。BTrace在使用上做了很多限制,如不能创建对象、不能使用数组、不能抛出或捕获异常、不能使用循环、不能使用synchronized关键字、脚本的属性和方法都必须使用static修饰等,具体限制条件可参考用户手册。根据官方声明,不当地使用BTrace可能导致JVM崩溃,如BTrace使用错误的.class文件,所以,可以先在本地验证BTrace脚本的正确性再使用
https://blog.csdn.net/coslay/article/details/43113029
https://www.cnblogs.com/163yun/p/10078137.html
asm:
0: aload_0
首先第一个0代表虚指令中的行号(后面会应到,确切说应该是方法的body部分第几个字节),每个方法从0开始顺序递增,但是可以跳跃,跳跃的原因在于一些指令还会接操作的内容,这些操作的内容可能来自常量池,也可以标志是第几个slot的本地变量,因此需要占用一定的空间。
aload_0指令是将“第1个”slot所在的本地变量推到栈顶,并且这个本地变量是引用类型的,相关的指令有:aload_[0-3](范围是:0x2a ~ 0x2d)。如果超过4个,则会使用“aload + 本地变量的slot位置”来完成(此时会多占用1个字节来存放),前者是通过具体的几个指令直接完成。
许多地方会解释为第1个引用类型的本地变量,但胖哥是一个逻辑怪,认为这句话有问题,并不是第1个引用变量,普通变量如果在它之前,它也不是第1个了,此时本身就是第1个本地变量,更确切地说是第一个slot所在位置的本地变量。
注意:
常量池的存放内容
存放所有的方法名
field名
方法签名(方法参数+返回值)
类型名
class文件中的常量值
常量池的前四部分可以称作是符号引用(即只有一些名称,但没有实际的地址,在运行期进行类的加载过后,会为这些东西分配实际的内存,到时候符号引用就会转化为直接引用,就能被JVM用了)
常量池的组成:符号引用、常量(这个常量包含我们代码中定义的常量,eg、字符串常量,也包括class文件中的常量,eg.SourceFile)。
主版本号的对应(eg.50对应jdk6,51对应jdk7),查看《深入理解java虚拟机(第二版)》P167
Stack:操作数栈的深度(这个值就是类加载阶段为操作数栈分配的深度)
Locals:局部变量的分配空间(单位是slot,不是个数),对于double和long这两个64bit的,需要两个slot,对于其他<=32bit的,只需要一个slot
Args_size:方法参数的个数,包括方法参数、this(this只针对实例方法,static方法不会自动添加this)
inc()方法:我详细注释了该方法的执行过程,这也就是JVM执行一个方法的基本流程(基于栈)
ClassReader.java
// visits the class declaration
classVisitor.visit(readInt(items[1] - 7), access, name, signature,
superClass, interfaces);
// visits the source and debug info
if ((flags & SKIP_DEBUG) == 0
&& (sourceFile != null || sourceDebug != null)) {
classVisitor.visitSource(sourceFile, sourceDebug);
}
// visits the module info and associated attributes
if (module != 0) {
readModule(classVisitor, context, module,
moduleMainClass, packages);
}
// visits the outer class
if (enclosingOwner != null) {
classVisitor.visitOuterClass(enclosingOwner, enclosingName,
enclosingDesc);
}
// visits the class annotations and type annotations
if (anns != 0) {
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true,
classVisitor.visitAnnotation(readUTF8(v, c), true));
}
}
if (ianns != 0) {
for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true,
classVisitor.visitAnnotation(readUTF8(v, c), false));
}
}
if (tanns != 0) {
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true,
classVisitor.visitTypeAnnotation(context.typeRef,
context.typePath, readUTF8(v, c), true));
}
}
if (itanns != 0) {
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true,
classVisitor.visitTypeAnnotation(context.typeRef,
context.typePath, readUTF8(v, c), false));
}
}
// visits the attributes
while (attributes != null) {
Attribute attr = attributes.next;
attributes.next = null;
classVisitor.visitAttribute(attributes);
attributes = attr;
}
// visits the inner classes
if (innerClasses != 0) {
int v = innerClasses + 2;
for (int i = readUnsignedShort(innerClasses); i > 0; --i) {
classVisitor.visitInnerClass(readClass(v, c),
readClass(v + 2, c), readUTF8(v + 4, c),
readUnsignedShort(v + 6));
v += 8;
}
}
// visits the fields and methods
u = header + 10 + 2 * interfaces.length;
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
u = readField(classVisitor, context, u);
}
u += 2;
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
u = readMethod(classVisitor, context, u);
}
// visits the end of the class
classVisitor.visitEnd();
引子
在正式讲述本文主题前,先看一下之前项目中遇到的几个问题
问题一
问题现象:18年12月底的时候线上有一台手机在 18:00~21:00之间频繁连接和断开连接
分析步骤:
1、客户端同事初步分析手机日志,发现有断开异常,看调用堆栈是业务代码抛出
image.png
2、联想到后台主动关闭连接时,不会写入mqtt 消息,所以输入流stream读不到数据属于正常现象。
另外问题发生时的日志已经被清除,只能查看客户端的其它日志,幸运的是当时有网络包可以分析
3、查看网络请求终于发现一些端倪:
image.png
image.png
客户端先是连接101.132.150.36,同时后台139.196.100.216断开客户端连接(18:00:53前的连接),18:01分客户端又继续连接139.196.100.216,形成循环连接的现象。
重点查看连接connack的返回结果,找到了突破口。
image.png
4、第二个红框值为3,代表需要重新注册。因个别手机在多用户场景会出现连接切换重连的情况,后台发现token不匹配就会进行重连,客户端已经针对此情况修复。
问题二
问题现象:5月初收到ups-receiver线程池任务队列阻塞的监控报警
分析步骤:
1、查看错误日志,并没有找到相应的线索,也没有异常的日志。
2、因为当天凌晨12点半发现,临时重启解决问题。
3、对比内外部的receiver,单独拆分了回执线程池处理,并发布上线观察。
4、果然第二天问题还是出现,打印jstack进行分析。
5、问题得到确认,回执写入mq时的线程被阻塞,联系中间件同事进行处理,问题得以解决。
image.png
其它烧脑问题
http://km.vivo.xyz/pages/viewpage.action?pageId=28500755
http://km.vivo.xyz/pages/viewpage.action?pageId=16279250
http://km.vivo.xyz/pages/viewpage.action?pageId=14488732
当前痛点:
梳理以上问题时都存在一个共同特点,业务在遇到一些比较难定位的问题时,往往只能查看日志,或者临时添加日志,但这也会带来一些麻烦,比如日志量过大,
进程重启问题不必现,需要临时发布版本(可能引入其它风险)等,或者只能反复jstack进行问题猜测,但效果都不理想。当然针对不同层次需求场景,有对应
的工具,比如内存占用过多,得不到释放,可以dump出文件,但是分析此文件也并不容易,有一定的成本。还有类似jconsole等工具,但已有的这些工具并不能
满足高级的应用场景,比如动态查看方法的入参/返回结果/某个成员变量的值就可以很快定位出问题。
解决方案:
一个比较好的解决方案是建设一个公司级的JVM智能分析平台 --- 开发人员可以根据不同场景输入参数快速定位问题,提前监测,并协助智能分析问题发生的根因。
jvm智能分析平台具备以下特点。
1、动态加载,目标程序无需重启
2、字节码编程、性能得到保障
3、web平台化操作
4、对目标方法的入参、异常、返回结果的分析
5、对目标方法内部代码的耗时的分析
6、对指定java实例数统计及size分析
7、与第三方jar进行隔离,代码无污染
8、对线程堆栈智能分析可能的问题原因
冰山一角
jdk1.5以后,jdk整合了一套有关虚拟机的JVMTI接口,可以供使用者调用,JVMTI的功能非常丰富,包含了访问虚拟机中线程/内存/堆/栈/类/方法/变量的方法。
开发者可以灵活使用这些特性,开发出很多高级功能,比如上述提到的功能,不过这些接口是C/C++的,实现起来有一定的难度。以下例举两个例子。
例一:
比如下面展示了一个比较有趣的例子---通过java类名查找进程中对应实例的数量,具本如下。
1、java端的统计调用功能由一个本地方法实现,通过jni的方式嵌入jvm中,具体实现通过c++代码去实现
image.png
2、监控程序启动时开启jvm统计对象数的功能
image.png
3、使用jvmit的方法迭代对象size及实例个数
image.png
4、最终结果,已之前java代码预期一致
image.png
除了通过jvmti实现上述功能(实现成本偏高),jdk还提供了instrument技术,可通过字节码转换进行实现相同的功能,并且功能更强大,
除了实现监测,还可以动态添加新的功能:)
例二:
这里例举给目标方法动态添加try/catch及一个局部变量int i = 20的例子,当然也可以增加耗时统计
1、Student类中最初的say方法
image.png
编译后Student的say方法字节码:
image.png
2、对目标方法进行添加字节码(部分代码)
image.png
3、编译后say方法的字节码
image.png
查看上图汇编后的字节码文件,istore_1已经将栈顶的int值20保存到了局部变量中,并且增加了try/catch的异常捕获
总结:字节码编程方式同样可以动态实现目标程序的变更,但底层也通过jvmti进行实现的,但是通过字节码简单化了jvmti的开发工作量,当然为了更好的理解
是有必要同时掌握jvmti指令及字节码指定的。以上只是字节码编程的冰山一角,这里不展开介绍了。
以下是 jvm智能分析平台架构图
image.png
该系统后期还可以衍生其它更强大的功能:比如通过web端拉取git代码在线调试线上环境(支付宝目前已有类似的功能)
成本:
关于系统人力评估(正式加两个外包-前端和后端各一人)
收益 :
1、智能分析系统,提前发现疑难、隐藏较深的问题,减少线上问题造成的损失。
2、节省定位问题成本,现在项目越来越多,系统逻辑也越来越复杂,通过该系统快速锁定问题原因。
发表评论
-
linux下如何查看nginx产生的core文件,并调试源码
2017-04-26 13:10 0背景:C下如果程序报段错误,无法定位问题。 在网上找了很多资料 ... -
如何提高输入输出流的读写效率。
2015-07-29 15:19 2107本文主要介绍我在压缩解压文件的过程中遇到的一些共性问题。 起 ... -
windows和linux下如何搭建ftp服务
2015-01-15 11:28 1211引言:FTP作为项目中传输、共享文件的利器,是在工作中必须掌握 ... -
如何玩转Spring的BeanPostProcessor.
2014-12-29 14:44 3197在Spring初始化bean的步骤中,有一步执行前缀/ ... -
超常用的linux命令
2014-12-11 17:51 1233问:如何让新加文件(文件夹)自动继承父文件夹的权限。 答:li ... -
私有内部静态类的讨论及使用
2014-12-09 11:08 1241内部类一直比较神秘 ... -
优秀文章转载
2014-12-08 09:18 1337git常用命令 git clone 代码分支 git sta ... -
一个主线程等待子线程执行完毕的例子
2014-11-21 18:29 1230背景:实际开发中经常会出现当前线程必须等待子线程执行完毕以后的 ... -
四步完成WebService服务端与客户端的调用
2014-10-31 11:20 21135内部系统之间数据传输使用RMI方式比较方便,但外部系统之 ... -
hadoop相关知识总结
2014-10-22 11:08 676在部署hadoop及运行过程中遇到的问题记录 ... -
如何解决JDK版本与profile设置不一样的问题。
2014-10-09 17:53 2741问题:linux下配置完JAVA环境变量后,查看版本与设置的不 ... -
如何设置ssh免密码登录
2014-10-09 16:46 846背景:linux下机器A如何直接登录到机器B 操作 ... -
如何设置ssh免密码登录
2014-10-09 16:41 0背景:linux下机器A直接登录到机器B 操作 ... -
远程调试服务端与客户端设置
2014-04-14 09:42 821服务端设置: 服务端的启动脚本里面添加以下语句: JAVA_O ... -
单元测试编写原则及如何使用jmockit
2014-03-25 11:34 5691通常在写单元测试 ... -
大数据中查找最大10个数---普通查找与堆查找的比较
2014-01-20 00:26 6177从一批数据中查找前10个最大值。正常的想法是构建一个10个数的 ... -
组件模型与双事件处理线程
2011-12-27 00:32 503-9223372036854775808 ~ 92233720 ... -
网元用户
2011-12-19 00:19 1466基本概念 ... -
多线程的批量线程同步解决方案
2011-04-28 00:45 198多线程运行时有待处理线程?试试看下面介绍的这个批量线程同步方法 ... -
今天终于发布了自己的校内网应用程序(图片浏览)
2010-06-13 11:41 1084感兴趣的同学可以访问这个地址,http://116.3.197 ...
相关推荐
asm-1.3.3.jar, asm-1.3.4.jar, asm-1.3.5.jar, asm-1.4.1.jar, asm-1.4.2.jar, asm-1.4.3.jar, asm-1.4.jar, asm-1.5.1.jar, asm-1.5.2.jar, asm-1.5.3.jar, asm-2.0.jar, asm-2.1.jar, asm-2.2.1-sources.jar, asm...
ASM1064是一款高性能的PCI Express to SATA 3.0桥接芯片,由ASMIC公司设计制造。这款芯片主要用于实现PCI Express接口与SATA接口之间的数据高速传输,广泛应用于存储扩展卡、固态硬盘控制器等领域。以下是关于ASM...
ASM 1351 是一款由ASMedia( ASM 微电子)公司开发的集成电路,主要应用于数据传输和接口控制领域。这个压缩包“ASM 1351.zip”包含了与ASM 1351相关的三个关键文件:一个固件升级工具、数据表以及设计套件。 1. **...
kmod-oracleasm-2.0.8-15.el6_9.x86_64 oracleasm-support-2.1.8-1.el6.x86_64 oracleasmlib-2.0.4-1.el6.x86_64 安装顺序: rpm -ivh kmod-oracleasm-2.0.8-15.el6_9.x86_64.rpm rpm -ivh oracleasm-support-2.1.8...
【标题】"cglib-2.2.jar asm-tree.jar asm-commons.jar asm.jar" 提供的是一组用于Java编程的库,它们主要用于实现动态代理和字节码操作。 【描述】"cglib动态代理模式jar包 cglib-2.2.jar asm-tree.jar asm-...
ASM文件的扩展名通常为`.asm`,它允许程序员对计算机硬件进行精确控制,尽管相比高级语言,学习曲线较为陡峭,但在某些特定场景,如系统编程或优化代码时,汇编语言显得尤为重要。 【asm.acp】和【asm.stx】是...
这套工具包括了ASM、ASM-Util、ASM-TREE和ASM-ANALYSIS等组件,每个都有其特定的功能和用途。 **ASM库**是核心部分,提供低级别的API来生成和解析Java字节码。ASM库允许开发者直接操作字节码,创建和修改类,甚至在...
asm-util-1.3.4.jar, asm-util-1.3.5.jar, asm-util-1.4.1.jar, asm-util-1.4.3.jar, asm-util-1.5.1.jar, asm-util-1.5.2.jar, asm-util-1.5.3.jar, asm-util-2.0.jar, asm-util-2.1.jar, asm-util-2.2.1-sources....
包含如下oracleasm包: kmod-oracleasm-2.0.6.rh1-3.el6.x86_64.rpm oracleasm-2.0.8-4.el6_6.src.rpm oracleasm-2.0.8-6.el6_7.src.rpm oracleasm-2.0.8-8.el7.src.rpm oracleasm-2.0.8-15.el7.centos.src.rpm ...
### asm操作指南(中文)知识点总结 #### 一、ASM框架简介 - **定义与功能**:ASM是一个Java字节码操纵框架,主要用于动态生成类或增强现有类的功能。通过直接生成二进制`.class`文件,ASM能够在类被加载到Java...
ASM1061是一款由ASMtek(Asmedia Technology Inc.)公司生产的高性能PCI Express (PCIe) to Serial Advanced Technology Attachment (SATA)桥接芯片,主要用于扩展计算机系统的SATA接口,使得硬件开发人员能够轻松地...
在本案例中,我们关注的是ASM330LHH,这是一款高性能的三轴加速度计和三轴陀螺仪传感器,由意法半导体(STMicroelectronics)制造。ASM330LHH广泛应用于运动检测、航姿参考系统、手势识别以及物联网设备中的动态平衡...
ASM1083 PCIe转PCI芯片数据表 ASM1083 PCIe转PCI芯片数据表是ASMedia TECHNOLOGY INC.公司出品的一款PCIe转PCI桥接芯片,其主要功能是将PCI Express(Peripheral Component Interconnect Express)接口转换为传统的...
在标题提到的"C-include-ASM.zip_asm中include_asm_c语言中嵌套asm",我们主要讨论的是如何在C程序中使用汇编代码,并且可能涉及到如何在汇编代码中包含其他汇编模块。 首先,让我们了解一下C语言嵌套汇编的基本...
**汇编插件 AsmDude 用于 Visual Studio 2022** AsmDude 是一款专为Visual Studio 2022设计的汇编语言插件,它极大地提升了开发人员在使用汇编语言时的工作效率和代码质量。这款插件对新手极其友好,即使是编程经验...
ASM1061是一款广泛应用在PCI-E到SATA转换中的控制器芯片,由ASMtek公司生产。这个"ASM1061资料文件.rar"压缩包包含了关于该芯片的详细设计资料,对于开发者、工程师或者硬件爱好者来说是极其宝贵的资源。下面我们将...
### Oracle 不使用 OracleASM 的包配置 ASM 磁盘配置方法 #### 概述 在 Oracle 数据库系统中,自动存储管理(ASM)是用于管理数据库文件的一种高性能、高可用性的解决方案。通常情况下,ASM 依赖于 Oracle 提供的 ...
《ASM330LHH1陀螺仪:高精度数据手册解析》 ASM330LHH1是一款高性能的固态陀螺仪,主要用于需要精确测量角速度的应用中。这款陀螺仪以其卓越的精度和稳定性,广泛应用于无人机、机器人导航、虚拟现实设备以及各类...
ASM4是中国Java开发者常用的一款字节码操作框架ASM的第四个主要版本,它主要用于动态生成和分析Java字节码。ASM是一个低级别的库,可以直接操作和生成类的字节码,这在创建编译器、代码分析工具以及运行时代码修改等...
ASM是汇编语言的文件扩展名,而EXE是Windows操作系统中的可执行文件格式。本主题将详细介绍如何使用提供的工具将ASM源代码转换为可以直接运行的EXE程序。 首先,我们需要了解汇编语言的基本概念。汇编语言是机器...