Javaダイナミックロードjarとclassファイルの実例解析
本論文の研究は主にJava動的ローディングjarとclassファイルの関連内容であり、具体的には以下の通りである。
JAVAにおけるクラスファイルのロードはダイナミックです。つまり、私たちが使う時にロードします。使わないと、私たちのクラスをロードしません。
JAVAは私たちに二つのダイナミックメカニズムを提供してくれます。第一は陰的機構である。第二は表示機構である。以下のとおりです
二つの方法:暗黙的メカニズム:newオブジェクト+呼び出しクラスの静的方法 明示的なメカニズム:java.lag.lassのforName()方法によってロードされます。
java.lag.lassLoaderのloadClassによってロードされます。
1、Class.forName
Class.forName()方法は二つの形式を持っています。 パラメータの説明: className-必要なクラスの完全な限定名(パッケージ名を含む必要があります。そうでないとエラーが発生します。) initialize-初期化クラス(スタティックコードブロックの初期化) loader-クラスをロードするためのクラスキャリア
一つのパラメータだけを呼び出したforName()メソッドは、Class.forName(class Name,true,loader)に相当します。
この二つの方法は最後に原生方法forName 0に接続します。
つのパラメータのforName()は、最後に呼び出したのはforName 0(name、initialize、loader)です。
new硎道化のあるクラスを使っても、一つのパラメータしかないクラス・forName()方法を使っても、内部には「ロードクラス+スタティックコードブロックを実行する」ステップが含まれています。
3つのパラメータを有するClass.forName()法を使用すると、第2のパラメータがfalseである場合、クラス加載器はクラスをローディングするだけで、スタティックコードブロックを初期化することはなく、このクラスを実装するときのみスタティックコードブロックが初期化され、スタティックコードブロックはクラスの最初のインスタンス化の時に初期化される。
2、java.lang.lassLoader
Class LoaderはLoad Classのために使われています。Classがロードされると、このクラスが引用したすべてのクラスもロードされます。また、このようなロードは再帰的です。つまり、AがBに引用されると、Bがロードされる時、Bも追加されます。Bがロードされる時、Cもロードされます。このように再帰してすべての必要なクラスがロードされるまで。
締め括りをつける
以上はJavaダイナミックロードjarとclassファイルの実例解析のすべての内容であり、皆さんの役に立つことを願っています。興味のある方は引き続き当駅の他のテーマを参照してください。友達のサポートに感謝します。
JAVAにおけるクラスファイルのロードはダイナミックです。つまり、私たちが使う時にロードします。使わないと、私たちのクラスをロードしません。
JAVAは私たちに二つのダイナミックメカニズムを提供してくれます。第一は陰的機構である。第二は表示機構である。以下のとおりです
二つの方法:
java.lag.lassLoaderのloadClassによってロードされます。
Class.forName()方法は二つの形式を持っています。
public static Class forName(String className)
public static Class forName(String className, boolean initialize,ClassLoader loader)
この二つの方法は最後に原生方法forName 0に接続します。
つのパラメータのforName()は、最後に呼び出したのはforName 0(name、initialize、loader)です。
new硎道化のあるクラスを使っても、一つのパラメータしかないクラス・forName()方法を使っても、内部には「ロードクラス+スタティックコードブロックを実行する」ステップが含まれています。
3つのパラメータを有するClass.forName()法を使用すると、第2のパラメータがfalseである場合、クラス加載器はクラスをローディングするだけで、スタティックコードブロックを初期化することはなく、このクラスを実装するときのみスタティックコードブロックが初期化され、スタティックコードブロックはクラスの最初のインスタンス化の時に初期化される。
2、java.lang.lassLoader
Class LoaderはLoad Classのために使われています。Classがロードされると、このクラスが引用したすべてのクラスもロードされます。また、このようなロードは再帰的です。つまり、AがBに引用されると、Bがロードされる時、Bも追加されます。Bがロードされる時、Cもロードされます。このように再帰してすべての必要なクラスがロードされるまで。
package com.demo.test;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
public class DynamicLoadDemo {
enum FileType {
JAR, CLASS, OTHER
}
static class MyClassLoader extends ClassLoader {
public synchronized Class<?> loadClass(String name, File file) throws FileNotFoundException {
Class<?> cls = findLoadedClass(name);
if(cls != null) {
return cls;
}
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
try {
while (true) {
len = fis.read(buffer);
if (len == -1) {
break;
}
baos.write(buffer, 0, len);
}
//FileInputStream flush , flush ( ) ,
//baos.flush();
byte[] data = baos.toByteArray();
return defineClass(null, data, 0, data.length);
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try {
baos.close();
}
catch (IOException e) {
e.printStackTrace();
}
try {
fis.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
public static void main(String[] args) {
String className = "com.demo.test.HelloWorld";
String paths[] = { "HelloWorld.jar", "HelloWorld.class" };
for (String path : paths) {
String lowerPath = path.toLowerCase();
FileType fileType = FileType.OTHER;
if (lowerPath.endsWith(".jar") || lowerPath.endsWith(".zip")) {
fileType = FileType.JAR;
} else if (lowerPath.endsWith(".class")) {
fileType = FileType.CLASS;
}
if (fileType == FileType.OTHER) {
return;
}
File file = new File(path);
if (!file.exists()) {
return;
}
try {
URL url = file.toURI().toURL();
System.out.println(url.toString());
Class<?> cls = null;
switch (fileType) {
case JAR:
URLClassLoader classLoader = new URLClassLoader(new URL[] { url }, Thread.currentThread().getContextClassLoader());
cls = classLoader.loadClass(className);
break;
case CLASS:
MyClassLoader myClassLoader = new MyClassLoader();
cls = myClassLoader.loadClass(className, file);
break;
default:
break;
}
if (cls == null) {
return;
}
//
Field field = cls.getDeclaredField("hello");
if (!field.isAccessible()) {
field.setAccessible(true);
}
System.out.println(field.get(cls.newInstance()));
//
Method staticMethod = cls.getDeclaredMethod("sayStaticHello", null);
if (!staticMethod.isAccessible()) {
staticMethod.setAccessible(true);
}
// void, null
staticMethod.invoke(cls, null);
//
Method method = cls.getDeclaredMethod("say", String.class);
if (!method.isAccessible()) {
method.setAccessible(true);
}
Object ret = method.invoke(cls.newInstance(), "hello world");
System.out.println(ret);
}
catch (MalformedURLException e) {
e.printStackTrace();
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
catch (NoSuchMethodException e) {
e.printStackTrace();
}
catch (SecurityException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
catch (IllegalArgumentException e) {
e.printStackTrace();
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
catch (InstantiationException e) {
e.printStackTrace();
}
catch (NoSuchFieldException e) {
e.printStackTrace();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
}
結果:締め括りをつける
以上はJavaダイナミックロードjarとclassファイルの実例解析のすべての内容であり、皆さんの役に立つことを願っています。興味のある方は引き続き当駅の他のテーマを参照してください。友達のサポートに感謝します。