まず、熱負荷は何ですか
簡単に言えば、コード更新の一部ので、原理はJavaのクラスローダによって達成され、プロジェクトを再起動しないでください。監視の欠如に積載クラスの安全性は、保証され、一般的な開発環境で使用し、開発効率を加速することができないことができます。一般的に開発者モードとして知られています。自己定義されたフロントローダ、JVMのクラスローダについての最初の話を達成するために。
二、JVMローダー
1、ブートストラップクラスローダ
。これらのクラスはある$ JAVA_HOME / JRE / libに/ RT;ブートローダーと呼ばれるブートストラップClassLoaderクラスは、親クラスローダのトップは、*、* java.utiなどのjava.langなどのコアクラスをロードし,,です.jar;
2、拡張クラスローダー
拡張クラスローダと呼ばれる拡張クラスローダは、%JAVA_HOME%/ JRE / libに/ ext /ディレクトリ、で拡張されたパッケージをロードする責任があります
3、アプリケーションクラスローダ
アプリケーション・クラス・ローダーと呼ばれるアプリケーションクラスローダは、クラスパス環境変数にクラスをロードするための責任があります
クラスローディング機構
どのように動作します:親クラスローダのデリゲートメカニズムの使用を、簡単な言葉で、最初のアプリケーションは、親がロードするために必要であれば、トップに、ロード、および親かどうかを判断していない場合、それは、あまりにもロードされたときにロードされているかどうかを判断しますその後、親クラスの位置に応じてパッケージをロードし、サブクラスは、必要な負荷を満たしていません。
利点:自身が、それはStringクラスのJDKパッケージにそれを交換するかどうか、文字列バッグを書いた場合は繰り返し荷重を避けるため、クラスローディングのセキュリティを保証することができますか?明らかではない、なぜならこの問題を回避するには、このメカニズムの使用。
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// 首先判断该类是否已经被加载过
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
//尝试让父类加载
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
//自定义加载,findClass是个空方法就是让我们重写的
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
复制代码
JVMは、クラスがそれを介してロードされているかどうかを判断する方法ですか?findLoadedClass(名)によって、そのクラスのブートローダーバイナリ名を与えられたこのローダーを記録しているJava仮想マシンで、バイナリ名のクラスが返されます。それ以外の場合は、nullを返します。
第三に、カスタムローダー
まず、新しいクラスを作成して、ClassLoaderを継承します。とにfindClass()メソッドを書き換えます。コメントの書き込み方法が有用でした。
public class MyClassLoader extends ClassLoader {
@Override
//通过名称找到具体class文件,并进行加载
protected Class<?> findClass(String name) {
byte[] b = loadClassData(name);
name = name.split("\\.")[1];
//然后通过defineClass()将二进制文件转化为Class对象
return super.defineClass(name, b, 0, b.length);
}
//这个方法就是将具体位置的class文件转化为二进制流
private byte[] loadClassData(String name) {
try {
name = name.replace(".", "\\");
FileInputStream fileInputStream = new FileInputStream(new File("D:\\IntelliJ IDEA 2019.1\\JavaHotFix\\" + name+".class"));
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int i = 0;
while ((i = fileInputStream.read()) != -1) {
byteArrayOutputStream.write(i);
}
fileInputStream.close();
return byteArrayOutputStream.toByteArray();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
复制代码
}簡単に定義されたオブジェクトおよびメソッドを定義します
public class People {
public void hello() {
System.out.println("我是People");
}
}
复制代码
テスト済み
public class Main {
public static void main(String[] args) {
while (true) {
try {
MyClassLoader myClassLoader = new MyClassLoader();
Class<?> clazz = myClassLoader.loadClass("src.People");
Object people = clazz.newInstance();
clazz.getMethod("hello").invoke(people);
Thread.sleep(2000);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
复制代码
出発後:このカタログのレベルは、最初に
起動後、人民ハローを変更する()メソッドは再再びのjavacを取得します プロジェクト構造:小さなバグ:人々は人々はクラスパスが親で、つまり、ロードされた直接つながると呼ばれるオリジナルの限界までローダーを使用していなかった、唯一のブレークポイントの後に見つけることが、繰り返し熱負荷につながることはできません直接書き込むダイレクト名の初めからAppClassLoaderクラスがロードされます。