Javaダイナミックロードjarとclassファイルの実例解析


本論文の研究は主にJava動的ローディングjarとclassファイルの関連内容であり、具体的には以下の通りである。
JAVAにおけるクラスファイルのロードはダイナミックです。つまり、私たちが使う時にロードします。使わないと、私たちのクラスをロードしません。
JAVAは私たちに二つのダイナミックメカニズムを提供してくれます。第一は陰的機構である。第二は表示機構である。以下のとおりです
二つの方法:
  • 暗黙的メカニズム:newオブジェクト+呼び出しクラスの静的方法
  • 明示的なメカニズム:java.lag.lassのforName()方法によってロードされます。
    java.lag.lassLoaderのloadClassによってロードされます。
  • 1、Class.forName
    Class.forName()方法は二つの形式を持っています。
  • public static Class forName(String className)
  • public static Class forName(String className, boolean initialize,ClassLoader loader)
  • パラメータの説明:
  • 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もロードされます。このように再帰してすべての必要なクラスがロードされるまで。
    
    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ファイルの実例解析のすべての内容であり、皆さんの役に立つことを願っています。興味のある方は引き続き当駅の他のテーマを参照してください。友達のサポートに感謝します。