`
ayufox
  • 浏览: 276461 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

[Java性能剖析]JPDA 4)Java Instrutment

    博客分类:
  • JVM
阅读更多

      在前面的介绍中,我们看到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)。

4
1
分享到:
评论

相关推荐

    深入Java调试体系(JPDA-JDWP)

    JPDA(Java Platform Debugger Architecture)是 Java 平台调试体系结构的缩写,通过 JPDA 提供的 API,开发人员可以方便灵活的搭建 Java 调试应用程序。 JPDA 主要由三个部分组成:Java 虚拟机工具接口(JVMTI),...

    基于JPDA的Java软件性能测试.pdf

    在基于JPDA的Java软件性能测试中,JPDA平台可以帮助开发者快速地对Java程序的性能和稳定性进行检测和分析,从而提高软件的整体质量。 基于JPDA的Java软件性能测试可以通过JPDA平台来进行简化测试,提高认软件的性能...

    JPDA----java调试体系

    JPDA(Java Platform Debugger Architecture)是 Java 平台调试体系结构的缩写,通过 JPDA 提供的 API,开发人员可以方便灵活的搭建 Java 调试应用程序。JPDA 主要由三个部分组成:Java 虚拟机工具接口(JVMTI),...

    使用JPDA进行Java程序远程调试

    Java Platform Debugger Architecture (JPDA) 是Java开发工具的一部分,它为开发者提供了强大的远程调试功能,使得可以在一台机器上调试运行在另一台机器上的Java应用程序。本文将详细介绍如何使用JPDA进行Java程序...

    JPDA.rar_JPDA数据关联_jpda_jpda关联_数据关联JPDA_跟踪波门

    标题中的"JPDA.rar"可能是指Java Platform Debugger Architecture(Java平台调试架构)的压缩文件,而"JPDA数据关联_jpda_jpda关联_数据关联JPDA_跟踪波门"这部分描述了与JPDA相关的特定应用或概念,特别是关于数据...

    Java程序优化与数据竞争检测的研究.pdf

    本文对Java程序优化与数据竞争检测的研究结果表明,Java程序优化是提高Java程序性能的重要手段,而JPDA平台是检测Java程序性能的重要技术。因此,在实际应用中,应充分利用Java程序优化和JPDA平台技术,提高Java程序...

    JPDA学习笔记与示例代码

    "数据挖掘及融合技术研究与应用_黄玲.caj"文件看起来是一篇关于数据挖掘和融合技术的研究论文,虽然不是直接关于JPDA,但它可能提供了相关领域的背景知识和应用案例,这对于理解目标跟踪的上下文环境和提高分析能力...

    远程调试jpda.docx

    JPDA是Java平台调试架构,它由Java虚拟机后端和调试平台前端两部分构成,使得调试平台可以通过调试交互协议向Java虚拟机请求服务,从而对运行在虚拟机中的程序进行调试。 具体到本文中,我们的应用服务器是Tomcat ...

    7_目标跟踪_jpda.zip

    标题中的“7_目标跟踪_jpda.zip”表明这是一个关于目标跟踪技术的压缩包,而“jpda”通常指的是Java Platform Debugger Architecture(Java平台调试架构)。这个压缩包可能包含了一系列有关如何使用JPDA进行目标跟踪...

    JPDA_jpda_目标跟踪_源码

    标题"JPDA_jpda_目标跟踪_源码"指的是Java Platform Debugger Architecture (JPDA)在目标跟踪方面的应用,且提供了源码。JPDA是Java开发工具的一部分,它提供了一组API和协议,允许开发者调试运行在Java虚拟机上的...

    Java调试体系及协议

    总的来说,Java调试体系及协议是Java开发不可或缺的一部分,它提供了强大的工具和接口,使得开发者能够在出现问题时快速定位和解决问题,从而提高软件的质量和性能。对于想要深入理解和优化Java应用的开发者来说,...

    Matlab_JPDA.zip_JPDA matlab仿真_JPDA算法_jpda_jpda tracking_matlab j

    多目标跟踪JPDA算法实现,是学习JPDA算法的经典代码,建议下载下来看看。

    JPDA_suanfa_jpda_航迹关联_JPDAmatlab仿真_

    4. **比较分析:** 可以对比其他数据关联算法(如Kalman滤波、概率数据关联PDA等),加深对JPDA的理解。 总之,这个压缩包提供的资源为初学者提供了一个实践JPDA算法的良好起点,通过学习和实验,不仅可以掌握JPDA...

    JPDA文章汇总

    JPDA常用于远程调试、自动化测试、性能分析等场合,特别适合分布式系统或云环境中的Java应用调试。 6. **源码分析:** 在“DemoCode”中,可能包含了利用JPDA进行调试的示例代码。通过分析这些代码,我们可以了解...

    JPDA算法程序.zip

    通过运行这些程序,用户可以模拟不同的雷达跟踪场景,调整参数以适应特定的杂波环境,或者评估不同初始条件下的跟踪性能。 **文件列表分析** 由于提供的文件列表只有一个:"JPDA算法程序",可以推断这可能是一个...

    java7帮助文档

    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 ...

    Java发展史_&_Java9、10新特性

    通过回顾Java的发展历程以及详细介绍Java 9的新特性,我们可以看出Java语言一直在不断进步,旨在提高开发者的生产力和应用程序的性能。模块化系统的引入尤其值得一提,它为Java的应用场景带来了革命性的变化,使其...

Global site tag (gtag.js) - Google Analytics