亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何在Java中使用Agent動態修改代碼

發布時間:2020-11-25 17:08:25 來源:億速云 閱讀:427 作者:Leah 欄目:編程語言

今天就跟大家聊聊有關如何在Java中使用Agent動態修改代碼,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。

需要兩個程序,一個是用來測試的程序,一個agent用于修改代碼。

1. 測試程序

被測試的程序包括:

  - ToString.Java

  - Foo.java

  - Main.java

具體代碼如下:

ToString.java:定義ToString注解

package com.chosen0ne.agent.test; 
 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
 
@Retention(RetentionPolicy.RUNTIME) 
public @interface ToString { 
} 

Foo.java:很簡單用于測試,使用了ToString注解

package com.chosen0ne.agent.test; 
 
@ToString 
public class Foo { 
 
} 

Main.java:

package com.chosen0ne.agent.test; 
 
public class Main { 
 public static void main(String[] args) { 
  Foo foo = new Foo(); 
  System.out.println(foo.toString()); 
 } 
} 

執行Main.java,結果如下:

com.chosen0ne.agent.test.Foo@7852e922

可以看到toString返回的是Object的默認實現。

2. Agent程序

java agent程序實際上類似于鉤子,有兩種方式:

  - main函數開始前

  - 程序運行中

這里主要測試main函數開始前的情況。類似于main函數,需要實現

public static void premain(String agentArgs, Instrumentation inst); 

這個函數會在main函數之前被調用。可以在premain中,進行字節碼操作,替換或重新實現一些類。這里使用Byte Buddy庫,在ASM之上提供了更高級的抽象,便于使用。

具體代碼如下:

package com.chosen0ne.ByteCode.agent; 
 
import java.lang.instrument.Instrumentation; 
 
import com.chosen0ne.agent.test.ToString; 
 
import net.bytebuddy.agent.builder.AgentBuilder; 
import net.bytebuddy.description.type.TypeDescription; 
import net.bytebuddy.dynamic.DynamicType.Builder; 
import net.bytebuddy.implementation.FixedValue; 
import net.bytebuddy.matcher.ElementMatchers; 
 
public class ToStringAgent { 
 
 public static void premain(String args, Instrumentation instrumentation) { 
  System.out.println("print pre main"); 
  new AgentBuilder.Default() 
    .type(ElementMatchers.isAnnotatedWith(ToString.class)) 
    .transform(new AgentBuilder.Transformer() { 
 
     @Override 
     public Builder<&#63;> transform(Builder<&#63;> builder, 
       TypeDescription typeDescription, ClassLoader classLoader) { 
      return builder.method(ElementMatchers.named("toString")) 
        .intercept(FixedValue.value("test")); 
     } 
      
    }).installOn(instrumentation); 
 } 
} 

agent需要打包成jar,并且對于premain的方式需要在MANIFEST.MF中指定Premain-Class,用于指明包含premain函數的類。具體有兩種方式打包:

 1)直接通過jar命令

編輯生成MANIFEST.MF后,執行:

jar cvfm agent.jar MANIFEST.MF -C . com lib 

上述命令打包成的jar包含:

  - com:編譯生成的class文件

  - lib:其依賴的庫

 2)通過maven直接生成:

通過maven-jar-plugin插件生成jar包,具體配置如下:

<build> 
 <plugins>  
  <plugin> 
   <groupId>org.apache.maven.plugins</groupId> 
   <artifactId>maven-jar-plugin</artifactId> 
   <version>2.1</version> 
   <configuration> 
    <archive> 
     <manifest> 
      <addClasspath>true</addClasspath> 
      <classpathPrefix>lib/</classpathPrefix> 
      <mainClass>com.chosen0ne.ByteCode.ByteBuddyTest</mainClass> 
     </manifest> 
     <manifestEntries> 
      <Premain-Class>com.chosen0ne.ByteCode.agent.ToStringAgent</Premain-Class> 
     </manifestEntries> 
    </archive> 
   </configuration> 
  </plugin> 
 </plugins> 
</build> 

主要通過manifestEntries標簽生成自動的屬性,這里指定了Premain-Class

3. 運行

將生成的agent.jar、依賴的ByteBuddy的jar包和測試程序編譯生成的class文件放到一個路徑下,目錄布局如下:

. 
├── agent.jar 
├── classes 
│ └── com 
│  └── chosen0ne 
│   └── agent 
│    └── test 
│     ├── Foo.class 
│     ├── Main.class 
│     └── ToString.class 
└── lib 
 └── byte-buddy-1.2.3.jar 

在當前目錄執行命令:

java -cp classes:lib/byte-buddy-1.2.3.jar -javaagent:agent.jar com.chosen0ne.agent.test.Main 

運行結果如下:

print pre main 
test 

這里需要注意一點,如果將測試程序也打包成jar包的話,那么在通過-cp指定ByteBuddy庫時會失敗,找不到對應的class,錯誤如下:

> java -cp classes:lib/byte-buddy-1.2.3.jar -javaagent:agent.jar -jar agent-test-case-0.0.1-SNAPSHOT.jar 
Exception in thread "main" java.lang.NoClassDefFoundError: net/bytebuddy/matcher/ElementMatcher 
 at java.lang.Class.getDeclaredMethods0(Native Method) 
 at java.lang.Class.privateGetDeclaredMethods(Class.java:2688) 
 at java.lang.Class.getDeclaredMethod(Class.java:2115) 
 at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:327) 
 at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:401) 
Caused by: java.lang.ClassNotFoundException: net.bytebuddy.matcher.ElementMatcher 
 at java.net.URLClassLoader$1.run(URLClassLoader.java:372) 
 at java.net.URLClassLoader$1.run(URLClassLoader.java:361) 
 at java.security.AccessController.doPrivileged(Native Method) 
 at java.net.URLClassLoader.findClass(URLClassLoader.java:360) 
 at java.lang.ClassLoader.loadClass(ClassLoader.java:424) 
 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) 
 at java.lang.ClassLoader.loadClass(ClassLoader.java:357) 
 ... 5 more 
FATAL ERROR in native method: processing of -javaagent failed 

看完上述內容,你們對如何在Java中使用Agent動態修改代碼有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

望江县| 仲巴县| 万宁市| 南部县| 诸暨市| 广西| 海盐县| 吕梁市| 昭觉县| 建湖县| 镇坪县| 常州市| 株洲县| 岳普湖县| 江都市| 永州市| 泾源县| 陵川县| 富锦市| 长兴县| 杭锦旗| 保亭| 桃园市| 平江县| 云霄县| 河东区| 司法| 新源县| 青神县| 讷河市| 常熟市| 华亭县| 太康县| 玛沁县| 龙海市| 吐鲁番市| 遂宁市| 邯郸县| 卫辉市| 淳化县| 通道|