2017-02-27 153 views
1

我一直在寫一個修改加載類的字節碼的Java代理。 我的代碼由4類:爲什麼我的Javassist類沒有在運行時執行?

  1. StackTraceAgent.java - 類的java劑與方法 的premain。
  2. StackTraceClassTransformer.java - 實現 java.lang.instrument.ClassFileTransformer。
  3. Student.java - 只是用於測試的自定義類。
  4. AgentTest - 具有方法main的簡單類。

可利用的庫:

  1. 了Javassist-3.20.0-GA.jar

StackTraceAgent.java,ClassFileTransformer.java和了Javassist-3.20.0-GA.jar被包裝在一個jar文件。它通過「-javaagent:MyJar.jar AgentTest」調用。我的問題是,使用javassist類編寫的代碼已經在runtume中調用。它只是由運行時傳遞而沒有任何錯誤,並且在最後程序繼續執行非javassist代碼直到結束。

我如何試圖解決這一問題:

  1. 我已審閱編譯的類。所有類都包含確切的代碼。
  2. 我覺得它是包裝成jar的東西有問題,但經過幾個小時的上網衝浪,我沒有找到任何有趣的東西。

MANIFEST.MF:

Manifest-Version: 1.0 
Premain-Class: agent.StackTraceAgent 

我的pom.xml文件:

<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <groupId>com.belenov</groupId> 
    <artifactId>TraceAgent</artifactId> 
    <version>1.0-SNAPSHOT</version> 

    <dependencies> 
     <!-- https://mvnrepository.com/artifact/org.javassist/javassist --> 
     <dependency> 
      <groupId>org.javassist</groupId> 
      <artifactId>javassist</artifactId> 
      <version>3.20.0-GA</version> 
     </dependency> 

    </dependencies> 

    <build> 
     <plugins> 

      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-dependency-plugin</artifactId> 
       <executions> 
        <execution> 
         <id>copy-dependencies</id> 
         <phase>prepare-package</phase> 
         <goals> 
          <goal>copy-dependencies</goal> 
         </goals> 
         <configuration> 
          <outputDirectory>${project.build.directory}/classes/lib</outputDirectory> 
          <overWriteReleases>false</overWriteReleases> 
          <overWriteSnapshots>false</overWriteSnapshots> 
          <overWriteIfNewer>true</overWriteIfNewer> 
         </configuration> 
        </execution> 
       </executions> 
      </plugin> 

      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-jar-plugin</artifactId> 
       <configuration> 
        <archive> 
         <manifestFile> 
          src/main/resources/META-INF/MANIFEST.MF 
         </manifestFile> 
         <manifest> 
          <addClasspath>false</addClasspath> 
         </manifest> 
        </archive> 
       </configuration> 
      </plugin> 
     </plugins> 
    </build> 
</project> 

StackTraceAgent.java:

import java.lang.instrument.Instrumentation; 
public class StackTraceAgent { 

    public static void premain(String args, Instrumentation instrumentation) { 
     System.out.println("instrument agent"); 
     StackTraceClassTransformer transformer = new StackTraceClassTransformer(); 
     instrumentation.addTransformer(transformer); 
    } 
} 

StackTraceClassTransformer.java:

import javassist.ClassPool; 
import javassist.CtClass; 
import javassist.CtMethod; 

import java.lang.instrument.ClassFileTransformer; 
import java.lang.instrument.IllegalClassFormatException; 
import java.security.ProtectionDomain; 

public class StackTraceClassTransformer implements ClassFileTransformer { 

    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, 
          ProtectionDomain protectionDomain, 
          byte[] classfileBuffer) throws IllegalClassFormatException { 

     try { 
      //the code below is passed up 
      ClassPool classPool = ClassPool.getDefault(); 
      CtClass ctClass = classPool.get(className); 
      CtMethod[] methods = ctClass.getMethods(); 

      for (CtMethod method : methods) { 
       method.insertAfter("System.out.println(\"Method name: \"+" + method.getName() + "+\" \"+" + method.getSignature() + ");"); 
       method.insertAfter("System.out.println(\"Object: \" + this.toString());"); 
      } 

      byte[] byteCode = ctClass.toBytecode(); 
      ctClass.detach(); 
      return byteCode; 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
     return null; 
    } 
} 

AgentTest.java

​​

Student.java

public class Student { 
    private String name; 
    private String surname; 

    public Student(String name, String surname) { 
     this.name = name; 
     this.surname = surname; 
    } 

    @Override 
    public String toString() { 
     return "Student{" + 
       "name='" + name + '\'' + 
       ", surname='" + surname + '\'' + 
       '}'; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getSurname() { 
     return surname; 
    } 

    public void setSurname(String surname) { 
     this.surname = surname; 
    } 
} 
+1

在wour清單文件,你不表示任何類路徑,特別是對於依賴,是故意的嗎? – Adonis

+0

你可以給我一些建議嗎?我想了解更多有關manifest的類。 –

+0

謝謝你的建議。 –

回答

1

基本上在manifest文件中,需要包括每個庫和資源程序中使用的類路徑中,可以添加在MANIFEST.MF中是這樣的行:

Class-Path: path/to/my/libraries 

一種方法可以簡單更新你的pom.xml,使用Maven Jar插件的清單部分:

<addClasspath>true</addClasspath> 
<classpathPrefix>${project.build.directory}/classes/lib</classpathPrefix> 
+0

非常感謝。它工作正常。 這也適用於我: $ {project.build.directory}/classes/lib

+0

總是一種樂趣 – Adonis

+0

classes/lib

相關問題