2017-02-27 280 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

相关问题