java instrumentation &JVMTI

來源:互聯網
上載者:User

標籤:style   blog   http   color   java   使用   os   io   

Java Instrumentation (參考:http://www.ibm.com/developerworks/cn/java/j-lo-jse61/)

簡介:

使用Instrumentation,開發人員可以構建獨立於應用程式的代理程式,用來檢測和協助運行在JVM上的程式,甚至能夠替換和修改某些類的定義

遇到問題:

運行在tomcat容器中的應用程式,由於main方法是在Bootstrap.jar中容器啟動時執行的,

Agent-class方式在替換的方法中只擷取到tomcat相關jar包中的一些類:

中是在transform方法中列印出來的,這個方法會在二中介紹

具體介紹:

下面是兩種方式PreMain 和 agentMain,分別為main函數執行之前,和執行之後的操作

一:PreMain

main函數執行之間,掃描判斷特定的類,然後以位元組數組的方式載入代理類的位元組碼檔案,替換目標類:

範例程式碼:

public class TransClass {    public int getNumber() {        return 2;    }}
TransClass

 

import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.lang.instrument.ClassFileTransformer;import java.lang.instrument.IllegalClassFormatException;import java.security.ProtectionDomain;class Transformer implements ClassFileTransformer {    public static final String classNumberReturns2 = "D://AOP//TransClass.class.2";    public static byte[] getBytesFromFile(String fileName) {    try {        // precondition        File file = new File(fileName);        InputStream is = new FileInputStream(file);        long length = file.length();        byte[] bytes = new byte[(int) length];            // Read in the bytes        int offset = 0;        int numRead = 0;        while (offset <bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {            offset += numRead;        }        if (offset < bytes.length) {            throw new IOException("Could not completely read file "+ file.getName());        }        is.close();        return bytes;        } catch (Exception e) {            System.out.println("error occurs in _ClassTransformer!"+ e.getClass().getName());            return null;        }    }    public byte[] transform(ClassLoader l, String className, Class<?> c,        ProtectionDomain pd, byte[] b) throws IllegalClassFormatException {        if (!className.equals("TransClass")) {            return null;        }        return getBytesFromFile(classNumberReturns2);    }} 
Transformer
public class TestMainInJar {    public static void main(String[] args) {        System.out.println(new TransClass().getNumber());    }}
TestMainInJar
import java.lang.instrument.UnmodifiableClassException;import java.lang.instrument.Instrumentation;public class Premain {public static void premain(String agentArgs, Instrumentation inst)    throws ClassNotFoundException, UnmodifiableClassException {        inst.addTransformer(new Transformer());    }} 
Premain
Manifest-Version: 1.0Premain-Class: Premain
MANIFEST.MF

步驟:

1. TransClass.java 中 改成 return 2; 之後編譯產生的TransClass.class改名為TransClass.class.2 ,以防止跟原TransClass.class重名

2. 打包:jar -cvf0 TestInstrument1.jar TransClass.class Transformer.class TestMainInJar.class Premain.class

            打好jar後替換manifest.mf檔案,(沒找到怎麼把這個檔案直接打進jar包)

3. 命令列執行

    1)java -javaagent:TestInstrument1.jar -cp TestInstrument1.jar TestMainInJar

    2)java -cp TestInstrument1.jar TestMainInJar

 (TransClass.class.2 和 TestInstrument1.jar 需要放置到  D:\AOP 目錄下)

    用第一個命令執行的時候,會把TransClass.class.2的內容載入進來替換jar包中的TransClass.class,而第二個命令是正常執行jar包中的TransClass.class

二: Agent-class

import java.lang.instrument.Instrumentation;public class LoadedAgent {    @SuppressWarnings("rawtypes")    public static void agentmain(String args, Instrumentation inst){        Class[] classes = inst.getAllLoadedClasses();    //inst.addTransformer(new Transformer());        for(Class cls :classes){            System.out.println(cls.getName());        }    }}
LoadedAgent

 

public class TargetVM {    public static void main(String[] args) throws InterruptedException{        while(true){            Thread.sleep(1000);        }    }}
TargetVM
import java.io.IOException;import com.sun.tools.attach.AgentInitializationException;import com.sun.tools.attach.AgentLoadException;import com.sun.tools.attach.AttachNotSupportedException;import com.sun.tools.attach.VirtualMachine;public class Test {    public static void main(String[] args) throws AttachNotSupportedException,            IOException, AgentLoadException, AgentInitializationException {        VirtualMachine vm = VirtualMachine.attach("1244");        vm.loadAgent("D:/AOP/agentmain/agentAop.jar");    }}
Test
Manifest-Version: 1.0Agent-Class: LoadedAgent
MANIFEST.MF

步驟:

    1. 將LoadedAgent.class 和 Manifest.mf打進jar包

    2. 執行TargetVM.class 擷取進程號PID

    3. 執行Test.class pid作為參數

  

注意:

    1. 編譯時間需要用到jdk中lib目錄下的tools.jar  javac -cp tools.jar Test.java

    2. 執行命令(1244 是進程號) :java -classpath "D:/AOP/agentmain/tools.jar" Test 1244    

 

   

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.