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 + -
显示快捷键?