在前面的介绍中,我们看到JVM TI的强大功能,然而,对于不熟悉C/C++语言的Java程序员来说,这扇门是不是真的就完全关闭了呢?还好,在关上了门的同时,JVM为我们提供了另一扇窗——Java Instrutment。其实Java Instrutment只提供了JVM TI中非常小的一个功能子集,一个是允许在类加载之前,修改类字节(ClassFileTransformer)(JDK5中开始提供,即使随JVM启动的Agent),另外一个是在类加载之后,触发JVM重新进行类加载(JDK6中开始提供,用于JVM启动之后通过Attach去加载Agent)。这两个功能表面看起来微不足道,但实际非常强大,AspectJ AOP的动态Weaving、Visual VM的性能剖析、JConsole支持Attach到进程上进行监控,都是通过这种方式来做的。除了这两个功能外,JDK 6中还提供了动态增加BootstrapClassLoader/SystemClassLoader的搜索路径、对Native方法进行instrutment(还记得JVM TI的Native Method Bind吗?)。
1.主要API(java.lang.instrutment)
1)ClassFileTransformer:定义了类加载前的预处理类,可以在这个类中对要加载的类的字节码做一些处理,譬如进行字节码增强
2)Instrutmentation:增强器,由JVM在入口参数中传递给我们,提供了如下的功能
- addTransformer/ removeTransformer:注册/删除ClassFileTransformer
- retransformClasses:对于已经加载的类重新进行转换处理,即会触发重新加载类定义,需要注意的是,新加载的类不能修改旧有的类声明,譬如不能增加属性、不能修改方法声明
- redefineClasses:与如上类似,但不是重新进行转换处理,而是直接把处理结果(bytecode)直接给JVM
- getAllLoadedClasses:获得当前已经加载的Class,可配合retransformClasses使用
- getInitiatedClasses:获得由某个特定的ClassLoader加载的类定义
- getObjectSize:获得一个对象占用的空间,包括其引用的对象
- appendToBootstrapClassLoaderSearch/appendToSystemClassLoaderSearch:增加BootstrapClassLoader/SystemClassLoader的搜索路径
- isNativeMethodPrefixSupported/setNativeMethodPrefix:支持拦截Native Method
我们后面通过范例来了解如何使用Java Instrutment技术。
2.随JVM启动的Agent
1)定义入口
public class StubPreMain
{
//另外一种入口格式是public static void premain(String agentArgs)
public static void premain(String agentArgs, Instrumentation inst)
throws ClassNotFoundException, UnmodifiableClassException
{
inst.addTransformer(new StubTransformer());
System.out.println("StubPreMain:Add StubTransformer");
}
}
我们的入口类格式必须是如上的premain(对应JVM TI的Agent_OnLoad方法),与JVM TI类似,JVM启动的时候回回调这个入口函数。在premain中我们最常见就是增加Transform,Transform允许我们在类加载器修改bytecode。一般性能剖析程序都是通过修改字节码,在方法进入和退出时收集时间数据来得出剖析数据的。
2)编写Transform
public class StubTransformer implements ClassFileTransformer
{
/*
* (non-Javadoc)
*
* @see java.lang.instrument.ClassFileTransformer#transform(java.lang.ClassLoader,
* java.lang.String, java.lang.Class, java.security.ProtectionDomain,
* byte[])
*/
public byte[] transform(ClassLoader loader, String className,
Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException
{
if ("ray.WebStub".equals(className))
{
System.out.println("Load WebStub From Transformer");
return readByte("WebStub.classbyte");
}
return null;
}
public byte[] readByte(String fileName)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = StubTransformer.class
.getResourceAsStream(fileName);
int BUFFER_SIZE = 1024;
byte[] buffer = new byte[BUFFER_SIZE];
int length = BUFFER_SIZE;
while (length == BUFFER_SIZE)
{
try
{
length = is.read(buffer);
baos.write(buffer, 0, length);
} catch (IOException e)
{
e.printStackTrace();
}
}
return baos.toByteArray();
}
}
这里简单地使用一个编译好的新的class的字节替换掉旧的class的字节,实际中我们当然不会使用这么苯的方法,实际上有各种字节码操作工具可以辅助我们完成这个任务
3)修改META-INF/ MANIFEST.MF
Manifest-Version: 1.0
Premain-Class: ray.StubPreMain
4)打成stubagent.jar,在启动参数中增加如下启动参数,启动JVM,当加载ray.WebStub这个类的时候,字节码会变成我们传进去的新的字节码
-javaagent:D:/Workspace/agent/stubagent.jar
3.通过Attach在JVM运行期间加载的Agent
这种Agent是JDK6才开始支持的,因此使用一般还是比较少的,我们来看一个实际使用范例,在前面的JVM Management API
的介绍中,我们知道,通过Attach API连接到JVM上,然后加载management-agent.jar,就可以在JVM中启动一个JMX代理。实际上management-agent.jar是一个支持通过Attach在JVM运行期间加载的Agent。management-agent.jar实际上只有一个META-INF/ MANIFEST.MF文件,内容如下:
Manifest-Version: 1.0
Created-By: 1.6.0 (Sun Microsystems Inc.)
Agent-Class: sun.management.Agent
Premain-Class: sun.management.Agent
可以看出这个包实际上既支持随JVM一起启动(我们前面看到的Premain-Class配置),也支持在JVM启动后通过Attach API去加载启动(看Agent-Class配置),我们通过反汇编看看sun.management.Agent是怎么做的。
sun.management.Agent定义了入口函数agentmain(对应于Agent_OnAttach方法)
public class Agent
{
public static void premain(String agentArgs)
throws Exception
{
agentmain(s);
}
public static void agentmain(String agentArgs)
throws Exception
{
….
}
}
与Premian-Agetn类似,另外一种入口函数格式是public static void premain(String agentArgs, Instrumentation inst)。
分享到:
相关推荐
JPDA(Java Platform Debugger Architecture)是 Java 平台调试体系结构的缩写,通过 JPDA 提供的 API,开发人员可以方便灵活的搭建 Java 调试应用程序。 JPDA 主要由三个部分组成:Java 虚拟机工具接口(JVMTI),...
在基于JPDA的Java软件性能测试中,JPDA平台可以帮助开发者快速地对Java程序的性能和稳定性进行检测和分析,从而提高软件的整体质量。 基于JPDA的Java软件性能测试可以通过JPDA平台来进行简化测试,提高认软件的性能...
JPDA(Java Platform Debugger Architecture)是 Java 平台调试体系结构的缩写,通过 JPDA 提供的 API,开发人员可以方便灵活的搭建 Java 调试应用程序。JPDA 主要由三个部分组成:Java 虚拟机工具接口(JVMTI),...
Java Platform Debugger Architecture (JPDA) 是Java开发工具的一部分,它为开发者提供了强大的远程调试功能,使得可以在一台机器上调试运行在另一台机器上的Java应用程序。本文将详细介绍如何使用JPDA进行Java程序...
标题中的"JPDA.rar"可能是指Java Platform Debugger Architecture(Java平台调试架构)的压缩文件,而"JPDA数据关联_jpda_jpda关联_数据关联JPDA_跟踪波门"这部分描述了与JPDA相关的特定应用或概念,特别是关于数据...
本文对Java程序优化与数据竞争检测的研究结果表明,Java程序优化是提高Java程序性能的重要手段,而JPDA平台是检测Java程序性能的重要技术。因此,在实际应用中,应充分利用Java程序优化和JPDA平台技术,提高Java程序...
"数据挖掘及融合技术研究与应用_黄玲.caj"文件看起来是一篇关于数据挖掘和融合技术的研究论文,虽然不是直接关于JPDA,但它可能提供了相关领域的背景知识和应用案例,这对于理解目标跟踪的上下文环境和提高分析能力...
JPDA是Java平台调试架构,它由Java虚拟机后端和调试平台前端两部分构成,使得调试平台可以通过调试交互协议向Java虚拟机请求服务,从而对运行在虚拟机中的程序进行调试。 具体到本文中,我们的应用服务器是Tomcat ...
标题中的“7_目标跟踪_jpda.zip”表明这是一个关于目标跟踪技术的压缩包,而“jpda”通常指的是Java Platform Debugger Architecture(Java平台调试架构)。这个压缩包可能包含了一系列有关如何使用JPDA进行目标跟踪...
标题"JPDA_jpda_目标跟踪_源码"指的是Java Platform Debugger Architecture (JPDA)在目标跟踪方面的应用,且提供了源码。JPDA是Java开发工具的一部分,它提供了一组API和协议,允许开发者调试运行在Java虚拟机上的...
4. **比较分析:** 可以对比其他数据关联算法(如Kalman滤波、概率数据关联PDA等),加深对JPDA的理解。 总之,这个压缩包提供的资源为初学者提供了一个实践JPDA算法的良好起点,通过学习和实验,不仅可以掌握JPDA...
总的来说,Java调试体系及协议是Java开发不可或缺的一部分,它提供了强大的工具和接口,使得开发者能够在出现问题时快速定位和解决问题,从而提高软件的质量和性能。对于想要深入理解和优化Java应用的开发者来说,...
多目标跟踪JPDA算法实现,是学习JPDA算法的经典代码,建议下载下来看看。
JPDA常用于远程调试、自动化测试、性能分析等场合,特别适合分布式系统或云环境中的Java应用调试。 6. **源码分析:** 在“DemoCode”中,可能包含了利用JPDA进行调试的示例代码。通过分析这些代码,我们可以了解...
通过运行这些程序,用户可以模拟不同的雷达跟踪场景,调整参数以适应特定的杂波环境,或者评估不同初始条件下的跟踪性能。 **文件列表分析** 由于提供的文件列表只有一个:"JPDA算法程序",可以推断这可能是一个...
Tool APIs java javac javadoc jar javap JPDA JConsole Java VisualVM Java DB Security Int'l RMI IDL Deploy Monitoring Troubleshoot Scripting JVM TI JRE RIAs Java Web Start Applet / Java Plug-in ...
在MatLab环境中实现JPDA算法,可以利用其强大的数学计算和图形可视化能力,使得算法的调试和结果分析变得更加直观。"Data_JPDAF.m"文件很可能是该算法的主程序,包含了JPDA算法的具体实现代码。通过运行这个文件,...