騷操作:不重啟 JVM,如何替換掉已經(jīng)加載的類?
點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)??
? 本文來源:美團(tuán)技術(shù)博客
Java對(duì)象行為 java.lang.instrument.Instrumentation 直接操作字節(jié)碼 BTrace Arthas 三生萬物
Java對(duì)象行為
publicclass Person{
?privateint age;
?private String name;
?public void speak(String str) {
? ?System.out.println(str);
}
?public Person(int age, String name) {
? ?this.age = age;
? ?this.name = name;
?}
}
Person personA = new Person(43, "lixunhuan");
personA.speak("我是李尋歡");
Person personB = new Person(23, "afei");
personB.speak("我是阿飛");
Method area is created on virtual machine startup, shared among all Java virtual machine threads and it is logically part of heap area. It stores per-class structures such as the run-time constant pool, field and method data, and the code for methods and constructors.
java.lang.instrument.Instrumentation?!?/section>java.lang.instrument.Instrumentation
This method is used to replace the definition of a class without reference to the existing class file bytes, as one might do when recompiling from source for fix-and-continue debugging. Where the existing class file bytes are to be transformed (for example in bytecode instrumentation) retransformClasses should be used.
The redefinition may change method bodies, the constant pool and attributes. The redefinition must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance. These restrictions maybe be lifted in future versions. The class file bytes are not checked, verified and installed until after the transformations have been applied, if the resultant bytes are in error this method will throw an exception.
直接操作字節(jié)碼
BTrace
在我們的工程中,誰來做這個(gè)尋找字節(jié)碼,修改字節(jié)碼,然后retransform的動(dòng)作呢?我們并非先知,不可能知道未來有沒有可能遇到文章開頭的這種問題??紤]到性價(jià)比,我們也不可能在每個(gè)工程中都開發(fā)一段專門做這些修改字節(jié)碼、重新加載字節(jié)碼的代碼。 如果JVM不在本地,在遠(yuǎn)程呢? 如果連ASM都不會(huì)用呢?能不能更通用一些,更“傻瓜”一些。
A safe, dynamic tracing tool for the Java platform.
package com.sun.btrace.samples;
import com.sun.btrace.annotations.*;
import com.sun.btrace.AnyType;
importstatic com.sun.btrace.BTraceUtils.*;
/**
* This sample demonstrates regular expression
* probe matching and getting input arguments
* as an array - so that any overload variant
* can be traced in "one place". This example
* traces any "readXX" method on any class in
* java.io package. Probed class, method and arg
* array is printed in the action.
*/
@BTracepublicclass ArgArray {
? ?@OnMethod(
? ? ? ?clazz="/java\\.io\\..*/",
? ? ? ?method="/read.*/"
? ?)
? ?public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args) {
? ? ? ?println(pcn);
? ? ? ?println(pmn);
? ? ? ?printArray(args);
? ?}
}
package com.sun.btrace.samples;
import com.sun.btrace.annotations.*;
importstatic com.sun.btrace.BTraceUtils.*;
import com.sun.btrace.annotations.Export;
/**
* This sample creates a jvmstat counter and
* increments it everytime Thread.start() is
* called. This thread count may be accessed
* from outside the process. The @Export annotated
* fields are mapped to jvmstat counters. The counter
* name is "btrace." + + "." +
*/
@BTracepublicclass ThreadCounter {
? ?// create a jvmstat counter using @Export
? ?@Exportprivatestaticlong count;
? ?@OnMethod(
? ? ? ?clazz="java.lang.Thread",
? ? ? ?method="start"
? ?)
? ?public static void onnewThread(@Self Thread t) {
? ? ? ?// updating counter is easy. Just assign to
? ? ? ?// the static field!
? ? ? ?count++;
? ?}
? ?@OnTimer(2000)
? ?public static void ontimer() {
? ? ? ?// we can access counter as "count" as well
? ? ? ?// as from jvmstat counter directly.
? ? ? ?println(count);
? ? ? ?// or equivalently ...
? ? ? ?println(Counters.perfLong("btrace.com.sun.btrace.samples.ThreadCounter.count"));
? ?}
}
BTrace腳本:利用BTrace定義的注解,我們可以很方便地根據(jù)需要進(jìn)行腳本的開發(fā)。 Compiler:將BTrace腳本編譯成BTrace class文件。 Client:將class文件發(fā)送到Agent。 Agent:基于Java的Attach API,Agent可以動(dòng)態(tài)附著到一個(gè)運(yùn)行的JVM上,然后開啟一個(gè)BTrace Server,接收client發(fā)過來的BTrace腳本;解析腳本,然后根據(jù)腳本中的規(guī)則找到要修改的類;修改字節(jié)碼后,調(diào)用Java Instrument的retransform接口,完成對(duì)對(duì)象行為的修改并使之生效。

不允許創(chuàng)建對(duì)象 不允許創(chuàng)建數(shù)組 不允許拋異常 不允許catch異常 不允許隨意調(diào)用其他對(duì)象或者類的方法,只允許調(diào)用com.sun.btrace.BTraceUtils中提供的靜態(tài)方法(一些數(shù)據(jù)處理和信息輸出工具) 不允許改變類的屬性 不允許有成員變量和方法,只允許存在static public void方法 不允許有內(nèi)部類、嵌套類 不允許有同步方法和同步塊 不允許有循環(huán) 不允許隨意繼承其他類(當(dāng)然,java.lang.Object除外) 不允許實(shí)現(xiàn)接口 不允許使用assert 不允許使用Class對(duì)象
Arthas
三生萬物
1.?監(jiān)控告警滿飛天,運(yùn)維在家睡到自然醒...
最近面試BAT,整理一份面試資料《Java面試BATJ通關(guān)手冊(cè)》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。
獲取方式:點(diǎn)“在看”,關(guān)注公眾號(hào)并回復(fù)?Java?領(lǐng)取,更多內(nèi)容陸續(xù)奉上。
文章有幫助的話,在看,轉(zhuǎn)發(fā)吧。
謝謝支持喲 (*^__^*)
評(píng)論
圖片
表情


