proxy.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 1,490 行 · 第 1/4 页

JAVA
1,490
字号
		return ((Proxy) proxy).h;
	}

	/**
	 * Optional native method to replace (and speed up) the pure Java
	 * implementation of getProxyClass.  Only needed if
	 * Configuration.HAVE_NATIVE_GET_PROXY_CLASS is true, this does the
	 * work of both getProxyData0 and generateProxyClass0 with no
	 * intermediate form in Java. The native code may safely assume that
	 * this class must be created, and does not already exist.
	 *
	 * @param loader the class loader to define the proxy class in; null
	 *        implies the bootstrap class loader
	 * @param interfaces the interfaces the class will extend
	 * @return the generated proxy class
	 * @throws IllegalArgumentException if the constraints for getProxyClass
	 *         were violated, except for problems with null
	 * @throws NullPointerException if `interfaces' is null or contains
	 *         a null entry, or if handler is null
	 * @see Configuration#HAVE_NATIVE_GET_PROXY_CLASS
	 * @see #getProxyClass(ClassLoader, Class[])
	 * @see #getProxyData0(ClassLoader, Class[])
	 * @see #generateProxyClass0(ProxyData)
	 */
	private static Class getProxyClass0(ClassLoader loader, Class[] interfaces) {
		return null;
	}

	/**
	 * Optional native method to replace (and speed up) the pure Java
	 * implementation of getProxyData.  Only needed if
	 * Configuration.HAVE_NATIVE_GET_PROXY_DATA is true. The native code
	 * may safely assume that a new ProxyData object must be created which
	 * does not duplicate any existing ones.
	 *
	 * @param loader the class loader to define the proxy class in; null
	 *        implies the bootstrap class loader
	 * @param interfaces the interfaces the class will extend
	 * @return all data that is required to make this proxy class
	 * @throws IllegalArgumentException if the constraints for getProxyClass
	 *         were violated, except for problems with null
	 * @throws NullPointerException if `interfaces' is null or contains
	 *         a null entry, or if handler is null
	 * @see Configuration.HAVE_NATIVE_GET_PROXY_DATA
	 * @see #getProxyClass(ClassLoader, Class[])
	 * @see #getProxyClass0(ClassLoader, Class[])
	 * @see ProxyType#getProxyData()
	 */
	private static ProxyData getProxyData0(ClassLoader loader, Class[] interfaces) {
		return null;
	}

	/**
	 * Optional native method to replace (and speed up) the pure Java
	 * implementation of generateProxyClass.  Only needed if
	 * Configuration.HAVE_NATIVE_GENERATE_PROXY_CLASS is true. The native
	 * code may safely assume that a new Class must be created, and that
	 * the ProxyData object does not describe any existing class.
	 *
	 * @param loader the class loader to define the proxy class in; null
	 *        implies the bootstrap class loader
	 * @param data the struct of information to convert to a Class. This
	 *        has already been verified for all problems except exceeding
	 *        VM limitations
	 * @return the newly generated class
	 * @throws IllegalArgumentException if VM limitations are exceeded
	 * @see #getProxyClass(ClassLoader, Class[])
	 * @see #getProxyClass0(ClassLoader, Class[])
	 * @see ProxyData#generateProxyClass(ClassLoader)
	 */
	private static Class generateProxyClass0(ClassLoader loader, ProxyData data) {
		return null;
	}

	/**
	 * Helper class for mapping unique ClassLoader and interface combinations
	 * to proxy classes.
	 *
	 * @author Eric Blake <ebb9@email.byu.edu>
	 */
	private static final class ProxyType {
		/**
		 * Store the class loader (may be null)
		 */
		final ClassLoader loader;

		/**
		 * Store the interfaces (never null, all elements are interfaces)
		 */
		final Class[] interfaces;

		/**
		 * Construct the helper object.
		 *
		 * @param loader the class loader to define the proxy class in; null
		 *        implies the bootstrap class loader
		 * @param interfaces an array of interfaces
		 */
		ProxyType(ClassLoader loader, Class[] interfaces) {
			if (loader == null)
				loader = ClassLoader.getSystemClassLoader();
			this.loader = loader;
			this.interfaces = interfaces;
		}

		/**
		 * Calculates the hash code.
		 *
		 * @return a combination of the classloader and interfaces hashcodes.
		 */
		public int hashCode() {
			//loader is always not null
			int hash = loader.hashCode();
			for (int i = 0; i < interfaces.length; i++)
				hash = hash * 31 + interfaces[i].hashCode();
			return hash;
		}

		// A more comprehensive comparison of two arrays,
		//   ignore array element order, and
		//   ignore redundant elements
		private static boolean sameTypes(Class arr1[], Class arr2[]) {
			if (arr1.length == 1 && arr2.length == 1) {
				return arr1[0] == arr2[0];
			}

			// total occurrance of elements of arr1 in arr2
			int total_occ_of_arr1_in_arr2 = 0;
			each_type : for (int i = arr1.length; --i >= 0;) {
				Class t = arr1[i];
				for (int j = i; --j >= 0;) {
					if (t == arr1[j]) { //found duplicate type
						continue each_type;
					}
				}

				// count c(a unique element of arr1)'s 
				//   occurrences in arr2
				int occ_in_arr2 = 0;
				for (int j = arr2.length; --j >= 0;) {
					if (t == arr2[j]) {
						++occ_in_arr2;
					}
				}
				if (occ_in_arr2 == 0) { // t does not occur in arr2
					return false;
				}

				total_occ_of_arr1_in_arr2 += occ_in_arr2;
			}
			// now, each element of arr2 must have been visited
			return total_occ_of_arr1_in_arr2 == arr2.length;
		}

		/**
		 * Calculates equality.
		 *
		 * @param the object to compare to
		 * @return true if it is a ProxyType with same data
		 */
		public boolean equals(Object other) {
			ProxyType pt = (ProxyType) other;
			if (loader != pt.loader || interfaces.length != pt.interfaces.length)
				return false;
			return sameTypes(interfaces, pt.interfaces);
		}
	} // class ProxyType

	/**
	 * Helper class which allows hashing of a method name and signature
	 * without worrying about return type, declaring class, or throws clause,
	 * and which reduces the maximally common throws clause between two methods
	 *
	 * @author Eric Blake <ebb9@email.byu.edu>
	 */
	private static final class ProxySignature {
		/**
		 * The core signatures which all Proxy instances handle.
		 */
		static final HashMap coreMethods = new HashMap();
		static {
			try {
				ProxySignature sig = new ProxySignature(Object.class.getMethod("equals", new Class[] { Object.class }));
				coreMethods.put(sig, sig);
				sig = new ProxySignature(Object.class.getMethod("hashCode", null));
				coreMethods.put(sig, sig);
				sig = new ProxySignature(Object.class.getMethod("toString", null));
				coreMethods.put(sig, sig);
			} catch (Exception e) {
				// assert false;
				throw (Error) new InternalError("Unexpected: " + e).initCause(e);
			}
		}

		/**
		 * The underlying Method object, never null
		 */
		final Method method;

		/**
		 * The set of compatible thrown exceptions, may be empty
		 */
		final Set exceptions = new HashSet();

		/**
		 * Construct a signature
		 *
		 * @param method the Method this signature is based on, never null
		 */
		ProxySignature(Method method) {
			this.method = method;
			Class[] exc = method.getExceptionTypes();
			int i = exc.length;
			while (--i >= 0) {
				// discard unchecked exceptions
				if (Error.class.isAssignableFrom(exc[i]) || RuntimeException.class.isAssignableFrom(exc[i]))
					continue;
				exceptions.add(exc[i]);
			}
		}

		/**
		 * Given a method, make sure it's return type is identical
		 * to this, and adjust this signature's throws clause appropriately
		 *
		 * @param other the signature to merge in
		 * @throws IllegalArgumentException if the return types conflict
		 */
		void checkCompatibility(ProxySignature other) {
			if (method.getReturnType() != other.method.getReturnType())
				throw new IllegalArgumentException("incompatible return types: " + method + ", " + other.method);

			// if you can think of a more efficient way than this O(n^2) search,
			// implement it!
			int size1 = exceptions.size();
			int size2 = other.exceptions.size();
			boolean[] valid1 = new boolean[size1];
			boolean[] valid2 = new boolean[size2];
			Iterator itr = exceptions.iterator();
			int pos = size1;
			while (--pos >= 0) {
				Class c1 = (Class) itr.next();
				Iterator itr2 = other.exceptions.iterator();
				int pos2 = size2;
				while (--pos2 >= 0) {
					Class c2 = (Class) itr2.next();
					if (c2.isAssignableFrom(c1))
						valid1[pos] = true;
					if (c1.isAssignableFrom(c2))
						valid2[pos2] = true;
				}
			}
			pos = size1;
			itr = exceptions.iterator();
			while (--pos >= 0) {
				itr.next();
				if (!valid1[pos])
					itr.remove();
			}
			pos = size2;
			itr = other.exceptions.iterator();
			while (--pos >= 0) {
				itr.next();
				if (!valid2[pos])
					itr.remove();
			}
			exceptions.addAll(other.exceptions);
		}

		/**
		 * Calculates the hash code.
		 *
		 * @return a combination of name and parameter types
		 */
		public int hashCode() {
			int hash = method.getName().hashCode();
			Class[] types = method.getParameterTypes();
			for (int i = 0; i < types.length; i++)
				hash = hash * 31 + types[i].hashCode();
			return hash;
		}

		/**
		 * Calculates equality.
		 *
		 * @param the object to compare to
		 * @return true if it is a ProxySignature with same data
		 */
		public boolean equals(Object other) {
			ProxySignature ps = (ProxySignature) other;
			Class[] types1 = method.getParameterTypes();
			Class[] types2 = ps.method.getParameterTypes();
			if (!method.getName().equals(ps.method.getName()) || types1.length != types2.length)
				return false;
			int i = types1.length;
			while (--i >= 0)
				if (types1[i] != types2[i])
					return false;
			return true;
		}
	} // class ProxySignature

	/**
	 * A flat representation of all data needed to generate bytecode/instantiate
	 * a proxy class.  This is basically a struct.
	 *
	 * @author Eric Blake <ebb9@email.byu.edu>
	 */
	private static final class ProxyData {
		/**
		 * The package this class is in.  Possibly null, meaning the unnamed
		 * package.
		 */
		Package pack;

		/**
		 * The interfaces this class implements.  Non-null, but possibly empty.
		 */
		Class[] interfaces;

		/**
		 * The Method objects this class must pass as the second argument to
		 * invoke (also useful for determining what methods this class has).
		 * Non-null, non-empty (includes at least Object.hashCode, Object.equals,
		 * and Object.toString).
		 */
		Method[] methods;

		/**
		 * The exceptions that do not need to be wrapped in
		 * UndeclaredThrowableException. exceptions[i] is the same as, or a
		 * subset of subclasses, of methods[i].getExceptionTypes(), depending on
		 * compatible throws clauses with multiple inheritance. It is unspecified
		 * if these lists include or exclude subclasses of Error and
		 * RuntimeException, but excluding them is harmless and generates a
		 * smaller class.
		 */
		Class[][] exceptions;

		/**
		 * For unique id's
		 */
		private static int count = 0;

		/**
		 * The id of this proxy class
		 */
		final int id = count++;

		/**
		 * Construct a ProxyData with uninitialized data members.
		 */
		ProxyData() {
		}

		/**
		 * Verifies that the arguments are legal, and sets up remaining data
		 * This should only be called when a class must be generated, as
		 * it is expensive.
		 *
		 * @param pt the ProxyType to convert to ProxyData
		 * @return the flattened, verified ProxyData structure for use in
		 *         class generation
		 * @throws IllegalArgumentException if `interfaces' contains
		 *         non-interfaces or incompatible combinations, and verify is true
		 * @throws NullPointerException if interfaces is null or contains null
		 */
		static ProxyData getProxyData(ProxyType pt) {
			Map method_set = (Map) ProxySignature.coreMethods.clone();
			boolean in_package = false; // true if we encounter non-public interface

			ProxyData data = new ProxyData();
			data.interfaces = pt.interfaces;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?