VM中不同ClassLoader權限的限制

package com.wy.classloader;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import sun.reflect.Reflection;

public class DiffClassLoderSamePackage {

	public static class Bean {

		String defaultFiled ;
		
		public String publicFiled ;
		
		protected String protectedFiled ;

		void defaultMethod(Bean b) {
		}
		
		protected void protectedMethod(Bean b) {
		}
		
		public void publicMethod(Bean b) {
		}
		
		public void publicMethod() {
		}
		
	}

	public static class ClassLader extends ClassLoader {

		/**
		 * 實現優先於父類加載類文件
		 */
		@Override
		public Class<?> loadClass(String name) throws ClassNotFoundException {

			Class<?> c = findLoadedClass(name);
			if (c != null) {
				return c;
			}
			byte[] b = getClassBytes(name);
			if (b != null) {
				return defineClass(name, b, 0, b.length);
			} else {
				return super.loadClass(name);
			}

		}

		/**
		 * 讀取class文件的內容
		 * 
		 * @param className
		 *            qualified類名
		 * @return 文件的字節內容, 異常或者找不到文件時返回null
		 */
		private byte[] getClassBytes(String className) {
			String path = System.getProperty("java.class.path") + File.separator
					+ className.replace('.', File.separatorChar) + ".class";
			FileInputStream fis = null;
			try {
				fis = new FileInputStream(path);
				byte[] bs = new byte[fis.available()];
				fis.read(bs);
				return bs;
			} catch (Exception e) {
				return null;
			} finally {
				try {
					if (fis != null) {
						fis.close();
					}
				} catch (IOException e) {
					// ignore
				}
			}

		}

	}

	public static void main(String[] args) throws Exception {

		// 由app ClassLoader加載
		Bean appB = new Bean();

		// 由自定義 ClassLoader加載
		ClassLader cust = new ClassLader();
		Class<?> custC = cust.loadClass("com.wy.classloader.DiffClassLoderSamePackage$Bean");
		
//		Object custB = (Bean)custC.newInstance();  //1. 不同類加載器加載的類,無法強制類型轉換
		Object custB = custC.newInstance();
		
//		default
//		Method custDefaultM = custC.getDeclaredMethod("defaultMethod", Bean.class); //2. 參數類型判定爲不一致
		Method custDefaultM = custC.getDeclaredMethod("defaultMethod", custC);
		
//		protected
//		Method custProtectedM = custC.getDeclaredMethod("protectedMethod", Bean.class); //2. 參數類型判定爲不一致
		Method custProtectedM = custC.getDeclaredMethod("protectedMethod", custC);
		
//		public
//		Method custPublicM = custC.getDeclaredMethod("publicMethod", Bean.class); //2. 參數類型判定爲不一致
		Method custPublicM = custC.getDeclaredMethod("publicMethod", custC);
		Method custPublicMethodNoArg= custC.getDeclaredMethod("publicMethod");
		
//		非public成員,當調用者的ClassLoader與加載Method所在Class的ClassLoader不一致時,無法訪問 . Reflection.ensureMemberAccess()
//		custDefaultM.invoke(custB, custB); //3. can not access a member of class with modifiers ""		
//		custProtectedM.invoke(custB, custB); //3. can not access a member of class with modifiers "protected"	
		
//		public方法通過調用者ClassLoader檢測,但對於接收者要進行ClassLoader類型檢測. 
//		custPublicM.invoke(appB, custB);// 4. object is not an instance of declaring class
//		custPublicM.invoke(appB, appB);// 4. object is not an instance of declaring class
//		custPublicMethodNoArg.invoke(appB);// 4. object is not an instance of declaring class
//		custPublicM.invoke(custB, appB);// 5. argument type mismatch
		custPublicMethodNoArg.invoke(custB); //ok
		custPublicM.invoke(custB, custB);// ok
		
//		非public成員,當調用者的ClassLoader與加載Method所在Class的ClassLoader不一致時,無法訪問 .Reflection.ensureMemberAccess()
		custC.getDeclaredField("defaultFiled").get(custB); //6. can not access a member of class with modifiers ""
//		custC.getDeclaredField("protectedFiled").get(custB); //6. can not access a member of class with modifiers "protected"
		
//		custC.getDeclaredField("publicFiled").get(appB); //7. Can not set java.lang.String field defaultFiled to Bean

		custC.getDeclaredField("publicFiled").get(custB); //ok
	}
}
3-6
Exception in thread "main" java.lang.IllegalAccessException: 
	at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
	at java.lang.reflect.Method.invoke(Method.java:588)
	at com.wy.classloader.DiffClassLoderSamePackage.main
4.
Exception in thread "main" java.lang.IllegalArgumentException: object is not an instance of declaring class
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at com.wy.classloader.DiffClassLoderSamePackage.main
5.
Exception in thread "main" java.lang.IllegalArgumentException: argument type mismatch
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at com.wy.classloader.DiffClassLoderSamePackage.main(DiffClassLoderSamePackage.java:121)
7.
Exception in thread "main" java.lang.IllegalArgumentException: Can not set java.lang.String field publicFiled to Bean
	at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
	at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
	at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:37)
	at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:18)
	at java.lang.reflect.Field.get(Field.java:358)
	at com.wy.classloader.DiffClassLoderSamePackage.main



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章