1 |
/* java.lang.reflect.Proxy |
/* Proxy.java -- build a proxy class that implements reflected interfaces |
2 |
Copyright (C) 2001 Free Software Foundation, Inc. |
Copyright (C) 2001, 2002 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
5 |
|
|
7 |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
8 |
the Free Software Foundation; either version 2, or (at your option) |
the Free Software Foundation; either version 2, or (at your option) |
9 |
any later version. |
any later version. |
10 |
|
|
11 |
GNU Classpath is distributed in the hope that it will be useful, but |
GNU Classpath is distributed in the hope that it will be useful, but |
12 |
WITHOUT ANY WARRANTY; without even the implied warranty of |
WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
39 |
package java.lang.reflect; |
package java.lang.reflect; |
40 |
|
|
41 |
import java.io.Serializable; |
import java.io.Serializable; |
42 |
// import java.protection.ProtectionDomain; |
import java.security.ProtectionDomain; |
43 |
import java.util.Map; |
import java.util.Map; |
44 |
import java.util.HashMap; |
import java.util.HashMap; |
45 |
import java.util.Set; |
import java.util.Set; |
46 |
import java.util.HashSet; |
import java.util.HashSet; |
47 |
import java.util.Iterator; |
import java.util.Iterator; |
48 |
import gnu.classpath.Configuration; |
import gnu.classpath.Configuration; |
49 |
|
import gnu.java.lang.reflect.TypeSignature; |
50 |
|
|
51 |
/** |
/** |
52 |
* This class allows you to dynamically create an instance of any (or |
* This class allows you to dynamically create an instance of any (or |
254 |
// synchronized so that we aren't trying to build the same class |
// synchronized so that we aren't trying to build the same class |
255 |
// simultaneously in two threads |
// simultaneously in two threads |
256 |
public static synchronized Class getProxyClass(ClassLoader loader, |
public static synchronized Class getProxyClass(ClassLoader loader, |
257 |
Class[] interfaces) |
Class[] interfaces) |
258 |
{ |
{ |
259 |
interfaces = (Class[]) interfaces.clone(); |
interfaces = (Class[]) interfaces.clone(); |
260 |
ProxyType pt = new ProxyType(loader, interfaces); |
ProxyType pt = new ProxyType(loader, interfaces); |
261 |
Class clazz = (Class) proxyClasses.get(pt); |
Class clazz = (Class) proxyClasses.get(pt); |
262 |
if (clazz == null) |
if (clazz == null) |
263 |
{ |
{ |
264 |
if (Configuration.HAVE_NATIVE_GET_PROXY_CLASS) |
if (Configuration.HAVE_NATIVE_GET_PROXY_CLASS) |
265 |
clazz = getProxyClass0(loader, interfaces); |
clazz = getProxyClass0(loader, interfaces); |
266 |
else |
else |
267 |
{ |
{ |
268 |
ProxyData data = (Configuration.HAVE_NATIVE_GET_PROXY_DATA |
ProxyData data = (Configuration.HAVE_NATIVE_GET_PROXY_DATA |
269 |
? getProxyData0(loader, interfaces) |
? getProxyData0(loader, interfaces) |
270 |
: ProxyData.getProxyData(pt)); |
: ProxyData.getProxyData(pt)); |
271 |
|
|
272 |
// FIXME workaround for bug in gcj 3.0.x |
// FIXME workaround for bug in gcj 3.0.x |
273 |
// Not needed with the latest gcj from cvs |
// Not needed with the latest gcj from cvs |
274 |
//clazz = (Configuration.HAVE_NATIVE_GENERATE_PROXY_CLASS |
//clazz = (Configuration.HAVE_NATIVE_GENERATE_PROXY_CLASS |
275 |
// ? generateProxyClass0(loader, data) |
// ? generateProxyClass0(loader, data) |
276 |
// : new ClassFactory(data).generate(loader)); |
// : new ClassFactory(data).generate(loader)); |
277 |
if (Configuration.HAVE_NATIVE_GENERATE_PROXY_CLASS) |
if (Configuration.HAVE_NATIVE_GENERATE_PROXY_CLASS) |
278 |
clazz = generateProxyClass0(loader, data); |
clazz = generateProxyClass0(loader, data); |
279 |
else |
else |
280 |
{ |
{ |
281 |
ClassFactory cf = new ClassFactory(data); |
ClassFactory cf = new ClassFactory(data); |
282 |
clazz = cf.generate(loader); |
clazz = cf.generate(loader); |
283 |
} |
} |
284 |
} |
} |
285 |
|
|
286 |
Object check = proxyClasses.put(pt, clazz); |
Object check = proxyClasses.put(pt, clazz); |
287 |
// assert check == null && clazz != null; |
// assert check == null && clazz != null; |
288 |
if (check != null || clazz == null) |
if (check != null || clazz == null) |
289 |
throw new InternalError(/*"Fatal flaw in getProxyClass"*/); |
throw new InternalError(/*"Fatal flaw in getProxyClass"*/); |
290 |
} |
} |
291 |
return clazz; |
return clazz; |
292 |
} |
} |
317 |
* @see Constructor#newInstance(Object[]) |
* @see Constructor#newInstance(Object[]) |
318 |
*/ |
*/ |
319 |
public static Object newProxyInstance(ClassLoader loader, |
public static Object newProxyInstance(ClassLoader loader, |
320 |
Class[] interfaces, |
Class[] interfaces, |
321 |
InvocationHandler handler) |
InvocationHandler handler) |
322 |
{ |
{ |
323 |
try |
try |
324 |
{ |
{ |
325 |
// getProxyClass() and Proxy() throw the necessary exceptions |
// getProxyClass() and Proxy() throw the necessary exceptions |
326 |
return getProxyClass(loader, interfaces) |
return getProxyClass(loader, interfaces) |
327 |
.getConstructor(new Class[] {InvocationHandler.class}) |
.getConstructor(new Class[] {InvocationHandler.class}) |
328 |
.newInstance(new Object[] {handler}); |
.newInstance(new Object[] {handler}); |
329 |
} |
} |
330 |
catch (RuntimeException e) |
catch (RuntimeException e) |
331 |
{ |
{ |
332 |
// Let IllegalArgumentException, NullPointerException escape. |
// Let IllegalArgumentException, NullPointerException escape. |
333 |
// assert e instanceof IllegalArgumentException |
// assert e instanceof IllegalArgumentException |
334 |
// || e instanceof NullPointerException; |
// || e instanceof NullPointerException; |
335 |
throw e; |
throw e; |
336 |
} |
} |
337 |
catch (InvocationTargetException e) |
catch (InvocationTargetException e) |
338 |
{ |
{ |
339 |
// Let wrapped NullPointerException escape. |
// Let wrapped NullPointerException escape. |
340 |
// assert e.getTargetException() instanceof NullPointerException |
// assert e.getTargetException() instanceof NullPointerException |
341 |
throw (NullPointerException) e.getTargetException(); |
throw (NullPointerException) e.getCause(); |
342 |
} |
} |
343 |
catch (Exception e) |
catch (Exception e) |
344 |
{ |
{ |
345 |
// Covers InstantiationException, IllegalAccessException, |
// Covers InstantiationException, IllegalAccessException, |
346 |
// NoSuchMethodException, none of which should be generated |
// NoSuchMethodException, none of which should be generated |
347 |
// if the proxy class was generated correctly. |
// if the proxy class was generated correctly. |
348 |
e.printStackTrace(); |
// assert false; |
349 |
// assert false; |
throw (Error) new InternalError("Unexpected: " + e).initCause(e); |
|
throw new InternalError(/*"Should not get here"*/); |
|
350 |
} |
} |
351 |
} |
} |
352 |
|
|
416 |
* @see #generateProxyClass0(ProxyData) |
* @see #generateProxyClass0(ProxyData) |
417 |
*/ |
*/ |
418 |
private static native Class getProxyClass0(ClassLoader loader, |
private static native Class getProxyClass0(ClassLoader loader, |
419 |
Class[] interfaces); |
Class[] interfaces); |
420 |
|
|
421 |
/** |
/** |
422 |
* Optional native method to replace (and speed up) the pure Java |
* Optional native method to replace (and speed up) the pure Java |
439 |
* @see ProxyType#getProxyData() |
* @see ProxyType#getProxyData() |
440 |
*/ |
*/ |
441 |
private static native ProxyData getProxyData0(ClassLoader loader, |
private static native ProxyData getProxyData0(ClassLoader loader, |
442 |
Class[] interfaces); |
Class[] interfaces); |
443 |
|
|
444 |
/** |
/** |
445 |
* Optional native method to replace (and speed up) the pure Java |
* Optional native method to replace (and speed up) the pure Java |
460 |
* @see ProxyData#generateProxyClass(ClassLoader) |
* @see ProxyData#generateProxyClass(ClassLoader) |
461 |
*/ |
*/ |
462 |
private static native Class generateProxyClass0(ClassLoader loader, |
private static native Class generateProxyClass0(ClassLoader loader, |
463 |
ProxyData data); |
ProxyData data); |
464 |
|
|
465 |
|
|
466 |
/** |
/** |
503 |
{ |
{ |
504 |
int hash = (loader == null) ? 0 : loader.hashCode(); |
int hash = (loader == null) ? 0 : loader.hashCode(); |
505 |
for (int i = 0; i < interfaces.length; i++) |
for (int i = 0; i < interfaces.length; i++) |
506 |
hash = hash * 31 + interfaces[i].hashCode(); |
hash = hash * 31 + interfaces[i].hashCode(); |
507 |
return hash; |
return hash; |
508 |
} |
} |
509 |
|
|
517 |
{ |
{ |
518 |
ProxyType pt = (ProxyType) other; |
ProxyType pt = (ProxyType) other; |
519 |
if (loader != pt.loader || interfaces.length != pt.interfaces.length) |
if (loader != pt.loader || interfaces.length != pt.interfaces.length) |
520 |
return false; |
return false; |
521 |
int i = interfaces.length; |
int i = interfaces.length; |
522 |
while (--i >= 0) |
while (--i >= 0) |
523 |
if (interfaces[i] != pt.interfaces[i]) |
if (interfaces[i] != pt.interfaces[i]) |
524 |
return false; |
return false; |
525 |
return true; |
return true; |
526 |
} |
} |
527 |
} // class ProxyType |
} // class ProxyType |
557 |
catch (Exception e) |
catch (Exception e) |
558 |
{ |
{ |
559 |
// assert false; |
// assert false; |
560 |
throw new InternalError(); |
throw (Error) new InternalError("Unexpected: " + e).initCause(e); |
561 |
} |
} |
562 |
} |
} |
563 |
|
|
601 |
void checkCompatibility(ProxySignature other) |
void checkCompatibility(ProxySignature other) |
602 |
{ |
{ |
603 |
if (method.getReturnType() != other.method.getReturnType()) |
if (method.getReturnType() != other.method.getReturnType()) |
604 |
throw new IllegalArgumentException("incompatible return types: " |
throw new IllegalArgumentException("incompatible return types: " |
605 |
+ method + ", " + other.method); |
+ method + ", " + other.method); |
606 |
|
|
607 |
// if you can think of a more efficient way than this O(n^2) search, |
// if you can think of a more efficient way than this O(n^2) search, |
613 |
Iterator itr = exceptions.iterator(); |
Iterator itr = exceptions.iterator(); |
614 |
int pos = size1; |
int pos = size1; |
615 |
while (--pos >= 0) |
while (--pos >= 0) |
616 |
{ |
{ |
617 |
Class c1 = (Class) itr.next(); |
Class c1 = (Class) itr.next(); |
618 |
Iterator itr2 = other.exceptions.iterator(); |
Iterator itr2 = other.exceptions.iterator(); |
619 |
int pos2 = size2; |
int pos2 = size2; |
620 |
while (--pos2 >= 0) |
while (--pos2 >= 0) |
621 |
{ |
{ |
622 |
Class c2 = (Class) itr2.next(); |
Class c2 = (Class) itr2.next(); |
623 |
if (c2.isAssignableFrom(c1)) |
if (c2.isAssignableFrom(c1)) |
624 |
valid1[pos] = true; |
valid1[pos] = true; |
625 |
if (c1.isAssignableFrom(c2)) |
if (c1.isAssignableFrom(c2)) |
626 |
valid2[pos2] = true; |
valid2[pos2] = true; |
627 |
} |
} |
628 |
} |
} |
629 |
pos = size1; |
pos = size1; |
630 |
itr = exceptions.iterator(); |
itr = exceptions.iterator(); |
631 |
while (--pos >= 0) |
while (--pos >= 0) |
632 |
{ |
{ |
633 |
itr.next(); |
itr.next(); |
634 |
if (! valid1[pos]) |
if (! valid1[pos]) |
635 |
itr.remove(); |
itr.remove(); |
636 |
} |
} |
637 |
pos = size2; |
pos = size2; |
638 |
itr = other.exceptions.iterator(); |
itr = other.exceptions.iterator(); |
639 |
while (--pos >= 0) |
while (--pos >= 0) |
640 |
{ |
{ |
641 |
itr.next(); |
itr.next(); |
642 |
if (! valid2[pos]) |
if (! valid2[pos]) |
643 |
itr.remove(); |
itr.remove(); |
644 |
} |
} |
645 |
exceptions.addAll(other.exceptions); |
exceptions.addAll(other.exceptions); |
646 |
} |
} |
647 |
|
|
655 |
int hash = method.getName().hashCode(); |
int hash = method.getName().hashCode(); |
656 |
Class[] types = method.getParameterTypes(); |
Class[] types = method.getParameterTypes(); |
657 |
for (int i = 0; i < types.length; i++) |
for (int i = 0; i < types.length; i++) |
658 |
hash = hash * 31 + types[i].hashCode(); |
hash = hash * 31 + types[i].hashCode(); |
659 |
return hash; |
return hash; |
660 |
} |
} |
661 |
|
|
671 |
Class[] types1 = method.getParameterTypes(); |
Class[] types1 = method.getParameterTypes(); |
672 |
Class[] types2 = ps.method.getParameterTypes(); |
Class[] types2 = ps.method.getParameterTypes(); |
673 |
if (! method.getName().equals(ps.method.getName()) |
if (! method.getName().equals(ps.method.getName()) |
674 |
|| types1.length != types2.length) |
|| types1.length != types2.length) |
675 |
return false; |
return false; |
676 |
int i = types1.length; |
int i = types1.length; |
677 |
while (--i >= 0) |
while (--i >= 0) |
678 |
if (types1[i] != types2[i]) |
if (types1[i] != types2[i]) |
679 |
return false; |
return false; |
680 |
return true; |
return true; |
681 |
} |
} |
682 |
} // class ProxySignature |
} // class ProxySignature |
761 |
// pool overflows |
// pool overflows |
762 |
int i = data.interfaces.length; |
int i = data.interfaces.length; |
763 |
while (--i >= 0) |
while (--i >= 0) |
764 |
{ |
{ |
765 |
Class inter = data.interfaces[i]; |
Class inter = data.interfaces[i]; |
766 |
if (! inter.isInterface()) |
if (! inter.isInterface()) |
767 |
throw new IllegalArgumentException("not an interface: " + inter); |
throw new IllegalArgumentException("not an interface: " + inter); |
768 |
try |
try |
769 |
{ |
{ |
770 |
if (Class.forName(inter.getName(), false, pt.loader) != inter) |
if (Class.forName(inter.getName(), false, pt.loader) != inter) |
771 |
throw new IllegalArgumentException("not accessible in " |
throw new IllegalArgumentException("not accessible in " |
772 |
+ "classloader: " + inter); |
+ "classloader: " + inter); |
773 |
} |
} |
774 |
catch (ClassNotFoundException e) |
catch (ClassNotFoundException e) |
775 |
{ |
{ |
776 |
throw new IllegalArgumentException("not accessible in " |
throw new IllegalArgumentException("not accessible in " |
777 |
+ "classloader: " + inter); |
+ "classloader: " + inter); |
778 |
} |
} |
779 |
if (! Modifier.isPublic(inter.getModifiers())) |
if (! Modifier.isPublic(inter.getModifiers())) |
780 |
if (in_package) |
if (in_package) |
781 |
{ |
{ |
782 |
Package p = inter.getPackage(); |
Package p = inter.getPackage(); |
790 |
in_package = true; |
in_package = true; |
791 |
data.pack = inter.getPackage(); |
data.pack = inter.getPackage(); |
792 |
} |
} |
793 |
for (int j = i; j >= 0; j--) |
for (int j = i; j >= 0; j--) |
794 |
if (data.interfaces[j] == inter) |
if (data.interfaces[j] == inter) |
795 |
throw new IllegalArgumentException("duplicate interface: " |
throw new IllegalArgumentException("duplicate interface: " |
796 |
+ inter); |
+ inter); |
797 |
Method[] methods = inter.getMethods(); |
Method[] methods = inter.getMethods(); |
798 |
int j = methods.length; |
int j = methods.length; |
799 |
while (--j >= 0) |
while (--j >= 0) |
800 |
{ |
{ |
801 |
ProxySignature sig = new ProxySignature(methods[j]); |
ProxySignature sig = new ProxySignature(methods[j]); |
802 |
ProxySignature old = (ProxySignature) method_set.put(sig, sig); |
ProxySignature old = (ProxySignature) method_set.put(sig, sig); |
803 |
if (old != null) |
if (old != null) |
804 |
sig.checkCompatibility(old); |
sig.checkCompatibility(old); |
805 |
} |
} |
806 |
} |
} |
807 |
|
|
808 |
i = method_set.size(); |
i = method_set.size(); |
809 |
data.methods = new Method[i]; |
data.methods = new Method[i]; |
810 |
data.exceptions = new Class[i][]; |
data.exceptions = new Class[i][]; |
811 |
Iterator itr = method_set.values().iterator(); |
Iterator itr = method_set.values().iterator(); |
812 |
while (--i >= 0) |
while (--i >= 0) |
813 |
{ |
{ |
814 |
ProxySignature sig = (ProxySignature) itr.next(); |
ProxySignature sig = (ProxySignature) itr.next(); |
815 |
data.methods[i] = sig.method; |
data.methods[i] = sig.method; |
816 |
data.exceptions[i] = (Class[]) sig.exceptions |
data.exceptions[i] = (Class[]) sig.exceptions |
817 |
.toArray(new Class[sig.exceptions.size()]); |
.toArray(new Class[sig.exceptions.size()]); |
818 |
} |
} |
819 |
return data; |
return data; |
820 |
} |
} |
821 |
} // class ProxyData |
} // class ProxyData |
836 |
private static final byte METHOD = 2; |
private static final byte METHOD = 2; |
837 |
private static final byte INTERFACE = 3; |
private static final byte INTERFACE = 3; |
838 |
private static final String CTOR_SIG |
private static final String CTOR_SIG |
839 |
= "(Ljava/lang/reflect/InvocationHandler;)V"; |
= "(Ljava/lang/reflect/InvocationHandler;)V"; |
840 |
private static final String INVOKE_SIG = "(Ljava/lang/Object;" |
private static final String INVOKE_SIG = "(Ljava/lang/Object;" |
841 |
+ "Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;"; |
+ "Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;"; |
842 |
|
|
843 |
/** Bytecodes for insertion in the class definition byte[] */ |
/** Bytecodes for insertion in the class definition byte[] */ |
844 |
private static final char ACONST_NULL = 1; |
private static final char ACONST_NULL = 1; |
918 |
// this_class |
// this_class |
919 |
qualName = ((data.pack == null ? "" : data.pack.getName() + '.') |
qualName = ((data.pack == null ? "" : data.pack.getName() + '.') |
920 |
+ "$Proxy" + data.id); |
+ "$Proxy" + data.id); |
921 |
putU2(classInfo(internal(qualName, false))); |
putU2(classInfo(TypeSignature.getEncodingOfClass(qualName, false))); |
922 |
// super_class |
// super_class |
923 |
putU2(classInfo("java/lang/reflect/Proxy")); |
putU2(classInfo("java/lang/reflect/Proxy")); |
924 |
|
|
926 |
putU2(data.interfaces.length); |
putU2(data.interfaces.length); |
927 |
// interfaces[] |
// interfaces[] |
928 |
for (int i = 0; i < data.interfaces.length; i++) |
for (int i = 0; i < data.interfaces.length; i++) |
929 |
putU2(classInfo(data.interfaces[i])); |
putU2(classInfo(data.interfaces[i])); |
930 |
|
|
931 |
// Recall that Proxy classes serialize specially, so we do not need |
// Recall that Proxy classes serialize specially, so we do not need |
932 |
// to worry about a <clinit> method for this field. Instead, we |
// to worry about a <clinit> method for this field. Instead, we |
1063 |
int handler_pc = code_length - 1; |
int handler_pc = code_length - 1; |
1064 |
StringBuffer signature = new StringBuffer("("); |
StringBuffer signature = new StringBuffer("("); |
1065 |
for (int j = 0; j < paramtypes.length; j++) |
for (int j = 0; j < paramtypes.length; j++) |
1066 |
signature.append(internal(paramtypes[j])); |
signature.append(TypeSignature.getEncodingOfClass(paramtypes[j])); |
1067 |
signature.append(")").append(internal(ret_type)); |
signature.append(")").append(TypeSignature.getEncodingOfClass(ret_type)); |
1068 |
|
|
1069 |
// Now we have enough information to emit the method. |
// Now we have enough information to emit the method. |
1070 |
|
|
1111 |
"Ljava/lang/reflect/InvocationHandler;")); |
"Ljava/lang/reflect/InvocationHandler;")); |
1112 |
putU1(ALOAD_0); |
putU1(ALOAD_0); |
1113 |
putU1(GETSTATIC); |
putU1(GETSTATIC); |
1114 |
putU2(refInfo(FIELD, internal(qualName, false), "m", |
putU2(refInfo(FIELD, TypeSignature.getEncodingOfClass(qualName, false), |
1115 |
"[Ljava/lang/reflect/Method;")); |
"m", "[Ljava/lang/reflect/Method;")); |
1116 |
putConst(i); |
putConst(i); |
1117 |
putU1(AALOAD); |
putU1(AALOAD); |
1118 |
if (paramtypes.length > 0) |
if (paramtypes.length > 0) |
1131 |
putU2(classInfo(wrapper(paramtypes[j]))); |
putU2(classInfo(wrapper(paramtypes[j]))); |
1132 |
putU1(DUP); |
putU1(DUP); |
1133 |
} |
} |
1134 |
putLoad(j, paramtypes[j]); |
putLoad(param_count, paramtypes[j]); |
1135 |
if (paramtypes[j].isPrimitive()) |
if (paramtypes[j].isPrimitive()) |
1136 |
{ |
{ |
1137 |
putU1(INVOKESPECIAL); |
putU1(INVOKESPECIAL); |
1138 |
putU2(refInfo(METHOD, wrapper(paramtypes[j]), "<init>", |
putU2(refInfo(METHOD, wrapper(paramtypes[j]), "<init>", |
1139 |
'(' + internal(paramtypes[j]) + ")V")); |
'(' + (TypeSignature |
1140 |
|
.getEncodingOfClass(paramtypes[j]) |
1141 |
|
+ ")V"))); |
1142 |
if (paramtypes[j] == long.class |
if (paramtypes[j] == long.class |
1143 |
|| paramtypes[j] == double.class) |
|| paramtypes[j] == double.class) |
1144 |
param_count++; |
param_count++; |
1162 |
putU1(INVOKEVIRTUAL); |
putU1(INVOKEVIRTUAL); |
1163 |
putU2(refInfo(METHOD, wrapper(ret_type), |
putU2(refInfo(METHOD, wrapper(ret_type), |
1164 |
ret_type.getName() + "Value", |
ret_type.getName() + "Value", |
1165 |
"()" + internal(ret_type))); |
"()" + TypeSignature.getEncodingOfClass(ret_type))); |
1166 |
if (ret_type == long.class) |
if (ret_type == long.class) |
1167 |
putU1(LRETURN); |
putU1(LRETURN); |
1168 |
else if (ret_type == float.class) |
else if (ret_type == float.class) |
1264 |
byte[] bytecode = new byte[pool.length() + stream.length()]; |
byte[] bytecode = new byte[pool.length() + stream.length()]; |
1265 |
// More efficient to bypass calling charAt() repetitively. |
// More efficient to bypass calling charAt() repetitively. |
1266 |
char[] c = pool.toString().toCharArray(); |
char[] c = pool.toString().toCharArray(); |
1267 |
for (int i = c.length - 1; i >= 0; i--) |
int i = c.length; |
1268 |
|
while (--i >= 0) |
1269 |
bytecode[i] = (byte) c[i]; |
bytecode[i] = (byte) c[i]; |
1270 |
c = stream.toString().toCharArray(); |
c = stream.toString().toCharArray(); |
1271 |
for (int i = c.length - 1, j = bytecode.length; i >= 0; i--, j--) |
i = c.length; |
1272 |
bytecode[j] = (byte) c[i]; |
int j = bytecode.length; |
1273 |
|
while (i > 0) |
1274 |
|
bytecode[--j] = (byte) c[--i]; |
1275 |
|
|
1276 |
// Patch the constant pool size, which we left at 0 earlier. |
// Patch the constant pool size, which we left at 0 earlier. |
1277 |
int count = poolEntries.size() + 1; |
int count = poolEntries.size() + 1; |
1279 |
bytecode[9] = (byte) count; |
bytecode[9] = (byte) count; |
1280 |
|
|
1281 |
try |
try |
1282 |
{ |
{ |
1283 |
// XXX Do we require more native support here? |
// XXX Do we require more native support here? |
1284 |
|
|
1285 |
// XXX Security hole - it is possible for another thread to grab the |
// XXX Security hole - it is possible for another thread to grab the |
1310 |
|
|
1311 |
// No security risk here, since clazz has not been exposed yet, |
// No security risk here, since clazz has not been exposed yet, |
1312 |
// so user code cannot grab the same reflection object. |
// so user code cannot grab the same reflection object. |
1313 |
Field f = clazz.getDeclaredField("m"); |
Field f = clazz.getDeclaredField("m"); |
1314 |
f.flag = true; |
f.flag = true; |
1315 |
// we can share the array, because it is not publicized |
// we can share the array, because it is not publicized |
1316 |
f.set(null, methods); |
f.set(null, methods); |
1317 |
f.flag = false; |
f.flag = false; |
1318 |
|
|
1319 |
return clazz; |
return clazz; |
1320 |
} |
} |
1321 |
catch (Throwable e) |
catch (Throwable e) |
1322 |
{ |
{ |
1323 |
e.printStackTrace(); |
// assert false; |
1324 |
// assert false; |
throw (Error) new InternalError("Unexpected: " + e).initCause(e); |
1325 |
throw new InternalError(/*"shouldn't get here"*/); |
} |
|
} |
|
1326 |
} |
} |
1327 |
|
|
1328 |
/** |
/** |
1405 |
} |
} |
1406 |
|
|
1407 |
/** |
/** |
|
* Given a fully-qualified Java type of the format returned by |
|
|
* Class.getName(), return the form for .class files. |
|
|
* |
|
|
* @param type the fully qualified type, in Java format |
|
|
* @param descriptor true if this is descriptor format (primitives and |
|
|
* L<name>; notation), false if class format |
|
|
* @return the internal representation of the type |
|
|
*/ |
|
|
private String internal(String type, boolean descriptor) |
|
|
{ |
|
|
if (! descriptor || type.charAt(0) == '[') |
|
|
return type.replace('.', '/'); |
|
|
if (type.equals("boolean")) |
|
|
return "Z"; |
|
|
if (type.equals("byte")) |
|
|
return "B"; |
|
|
if (type.equals("short")) |
|
|
return "S"; |
|
|
if (type.equals("char")) |
|
|
return "C"; |
|
|
if (type.equals("int")) |
|
|
return "I"; |
|
|
if (type.equals("long")) |
|
|
return "J"; |
|
|
if (type.equals("float")) |
|
|
return "F"; |
|
|
if (type.equals("double")) |
|
|
return "D"; |
|
|
if (type.equals("void")) |
|
|
return "V"; |
|
|
return 'L' + type.replace('.', '/') + ';'; |
|
|
} |
|
|
|
|
|
/** |
|
|
* Given a Class object, return the internal version for .class files. |
|
|
* |
|
|
* @param clazz the class object |
|
|
* @return the internal representation of the type |
|
|
*/ |
|
|
private String internal(Class clazz) |
|
|
{ |
|
|
return internal(clazz.getName(), true); |
|
|
} |
|
|
|
|
|
/** |
|
1408 |
* Given a primitive type, return its wrapper class name. |
* Given a primitive type, return its wrapper class name. |
1409 |
* |
* |
1410 |
* @param clazz the primitive type (but not void.class) |
* @param clazz the primitive type (but not void.class) |
1469 |
*/ |
*/ |
1470 |
private char classInfo(Class clazz) |
private char classInfo(Class clazz) |
1471 |
{ |
{ |
1472 |
return classInfo(internal(clazz.getName(), false)); |
return classInfo(TypeSignature.getEncodingOfClass(clazz.getName(), |
1473 |
|
false)); |
1474 |
} |
} |
1475 |
|
|
1476 |
/** |
/** |
1543 |
if (c > 0 && c <= '\u007f') |
if (c > 0 && c <= '\u007f') |
1544 |
sb.append(c); |
sb.append(c); |
1545 |
else if (c <= '\u07ff') // includes '\0' |
else if (c <= '\u07ff') // includes '\0' |
1546 |
{ |
{ |
1547 |
sb.append((char) (0xc0 | (c >> 6))); |
sb.append((char) (0xc0 | (c >> 6))); |
1548 |
sb.append((char) (0x80 | (c & 0x6f))); |
sb.append((char) (0x80 | (c & 0x6f))); |
1549 |
} |
} |
1550 |
else |
else |
1551 |
{ |
{ |
1552 |
sb.append((char) (0xe0 | (c >> 12))); |
sb.append((char) (0xe0 | (c >> 12))); |
1553 |
sb.append((char) (0x80 | ((c >> 6) & 0x6f))); |
sb.append((char) (0x80 | ((c >> 6) & 0x6f))); |
1554 |
sb.append((char) (0x80 | (c & 0x6f))); |
sb.append((char) (0x80 | (c & 0x6f))); |