From: <ls...@us...> - 2008-12-18 18:35:03
|
Revision: 4794 http://jnode.svn.sourceforge.net/jnode/?rev=4794&view=rev Author: lsantha Date: 2008-12-18 18:34:56 +0000 (Thu, 18 Dec 2008) Log Message: ----------- Integrated java.lang.reflect.Method from OpenJDK. Modified Paths: -------------- trunk/builder/src/builder/org/jnode/build/AbstractBootImageBuilder.java trunk/core/src/core/org/jnode/vm/classmgr/VmMethod.java trunk/core/src/core/org/jnode/vm/isolate/VmIsolate.java trunk/core/src/openjdk/vm/sun/reflect/NativeNativeMethodAccessorImpl.java trunk/gui/src/awt/org/jnode/awt/swingpeers/SwingToolkit.java Added Paths: ----------- trunk/core/src/openjdk/java/java/lang/reflect/Method.java Removed Paths: ------------- trunk/core/src/classpath/vm/java/lang/reflect/Method.java Modified: trunk/builder/src/builder/org/jnode/build/AbstractBootImageBuilder.java =================================================================== --- trunk/builder/src/builder/org/jnode/build/AbstractBootImageBuilder.java 2008-12-17 13:58:56 UTC (rev 4793) +++ trunk/builder/src/builder/org/jnode/build/AbstractBootImageBuilder.java 2008-12-18 18:34:56 UTC (rev 4794) @@ -1281,7 +1281,7 @@ addCompileHighOptLevel("java.io"); addCompileHighOptLevel("java.lang"); addCompileHighOptLevel("java.lang.ref"); - addCompileHighOptLevel("java.lang.reflect"); +// addCompileHighOptLevel("java.lang.reflect"); //<- produces inconsistent bootimage addCompileHighOptLevel("java.net"); addCompileHighOptLevel("java.nio"); addCompileHighOptLevel("java.security"); @@ -1332,18 +1332,18 @@ addCompileHighOptLevel("org.jnode.vm.memmgr.mmtk.ms"); //todo review for boot image size reduction - addCompileHighOptLevel("sun.misc"); +// addCompileHighOptLevel("sun.misc"); // addCompileHighOptLevel("sun.reflect"); <-- // this kills jnode while booting, maybe Reflection static{...} - addCompileHighOptLevel("sun.reflect.annotation"); - addCompileHighOptLevel("sun.reflect.generics"); - addCompileHighOptLevel("sun.reflect.generics.factory"); - addCompileHighOptLevel("sun.reflect.generics.parser"); - addCompileHighOptLevel("sun.reflect.generics.reflectiveObjects"); - addCompileHighOptLevel("sun.reflect.generics.repository"); - addCompileHighOptLevel("sun.reflect.generics.scope"); - addCompileHighOptLevel("sun.reflect.generics.tree"); - addCompileHighOptLevel("sun.reflect.generics.visitor"); - addCompileHighOptLevel("sun.reflect.misc"); +// addCompileHighOptLevel("sun.reflect.annotation"); +// addCompileHighOptLevel("sun.reflect.generics"); +// addCompileHighOptLevel("sun.reflect.generics.factory"); +// addCompileHighOptLevel("sun.reflect.generics.parser"); +// addCompileHighOptLevel("sun.reflect.generics.reflectiveObjects"); +// addCompileHighOptLevel("sun.reflect.generics.repository"); +// addCompileHighOptLevel("sun.reflect.generics.scope"); +// addCompileHighOptLevel("sun.reflect.generics.tree"); +// addCompileHighOptLevel("sun.reflect.generics.visitor"); +// addCompileHighOptLevel("sun.reflect.misc"); addCompileHighOptLevel("sun.nio"); if (false) { Deleted: trunk/core/src/classpath/vm/java/lang/reflect/Method.java =================================================================== --- trunk/core/src/classpath/vm/java/lang/reflect/Method.java 2008-12-17 13:58:56 UTC (rev 4793) +++ trunk/core/src/classpath/vm/java/lang/reflect/Method.java 2008-12-18 18:34:56 UTC (rev 4794) @@ -1,613 +0,0 @@ -/* java.lang.reflect.Method - reflection of Java methods - Copyright (C) 1998, 2001, 2002, 2005 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package java.lang.reflect; - -import gnu.java.lang.ClassHelper; -import java.lang.annotation.Annotation; -import java.lang.annotation.AnnotationFormatError; -import java.util.ArrayList; - -import org.jnode.vm.VmReflection; -import org.jnode.vm.classmgr.VmExceptions; -import org.jnode.vm.classmgr.VmMethod; -import gnu.java.lang.reflect.MethodSignatureParser; - -import java.util.Arrays; -import java.util.Map; -import java.nio.ByteBuffer; -import sun.reflect.MethodAccessor; -import sun.reflect.annotation.AnnotationParser; -import sun.reflect.annotation.AnnotationType; -import sun.misc.SharedSecrets; - -/** - * The Method class represents a member method of a class. It also allows - * dynamic invocation, via reflection. This works for both static and - * instance methods. Invocation on Method objects knows how to do - * widening conversions, but throws {@link IllegalArgumentException} if - * a narrowing conversion would be necessary. You can query for information - * on this Method regardless of location, but invocation access may be limited - * by Java language access controls. If you can't do it in the compiler, you - * can't normally do it here either.<p> - * - * <B>Note:</B> This class returns and accepts types as Classes, even - * primitive types; there are Class types defined that represent each - * different primitive type. They are <code>java.lang.Boolean.TYPE, - * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class, - * byte.class</code>, etc. These are not to be confused with the - * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are - * real classes.<p> - * - * Also note that this is not a serializable class. It is entirely feasible - * to make it serializable using the Externalizable interface, but this is - * on Sun, not me. - * - * @author John Keiser - * @author Eric Blake <eb...@em...> - * @see Member - * @see Class - * @see java.lang.Class#getMethod(String,Class[]) - * @see java.lang.Class#getDeclaredMethod(String,Class[]) - * @see java.lang.Class#getMethods() - * @see java.lang.Class#getDeclaredMethods() - * @since 1.1 - * @status updated to 1.4 - */ -public final class Method extends AccessibleObject implements Member, AnnotatedElement, GenericDeclaration { - - private VmMethod vmMethod; - private ArrayList<Class> parameterTypes; - private ArrayList<Class> exceptionTypes; - - private static final int METHOD_MODIFIERS - = Modifier.ABSTRACT | Modifier.FINAL | Modifier.NATIVE - | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC - | Modifier.STATIC | Modifier.STRICT | Modifier.SYNCHRONIZED; - - /** - * - */ - public Method(VmMethod vmMethod) { - this.vmMethod = vmMethod; - this.annotationDefault = vmMethod.getRawAnnotationDefault(); - this.annotations = vmMethod.getRawAnnotations(); - this.parameterAnnotations = vmMethod.getRawParameterAnnotations(); - } - - public Method(Class declaringClass, String name, Class[] parameterTypes, Class returnType, Class[] checkedExceptions, int modifiers, int slot, String signature, byte[] annotations, byte[] parameterAnnotations, byte[] annotationDefault) { - - throw new UnsupportedOperationException(); - } - - /** - * Gets the class that declared this method, or the class where this method - * is a non-inherited member. - * @return the class that declared this member - */ - public Class<?> getDeclaringClass() - { - return vmMethod.getDeclaringClass().asClass(); - } - - /** - * Gets the name of this method. - * @return the name of this method - */ - public String getName() - { - return vmMethod.getName(); - } - - /** - * Return the raw modifiers for this method. - * @return the method's modifiers - */ - private int getModifiersInternal() - { - return vmMethod.getModifiers(); - } - - /** - * Gets the modifiers this method uses. Use the <code>Modifier</code> - * class to interpret the values. A method can only have a subset of the - * following modifiers: public, private, protected, abstract, static, - * final, synchronized, native, and strictfp. - * - * @return an integer representing the modifiers to this Member - * @see Modifier - */ - public int getModifiers() - { - return getModifiersInternal() & METHOD_MODIFIERS; - } - - /** - * Return true if this method is a bridge method. A bridge method - * is generated by the compiler in some situations involving - * generics and inheritance. - * @since 1.5 - */ - public boolean isBridge() - { - return (getModifiersInternal() & Modifier.BRIDGE) != 0; - } - - /** - * Return true if this method is synthetic, false otherwise. - * @since 1.5 - */ - public boolean isSynthetic() - { - return (getModifiersInternal() & Modifier.SYNTHETIC) != 0; - } - - /** - * Return true if this is a varargs method, that is if - * the method takes a variable number of arguments. - * @since 1.5 - */ - public boolean isVarArgs() - { - return (getModifiersInternal() & Modifier.VARARGS) != 0; - } - - /** - * Gets the return type of this method. - * @return the type of this method - */ - public Class<?> getReturnType() - { - return vmMethod.getReturnType().asClass(); - } - - /** - * Get the parameter list for this method, in declaration order. If the - * method takes no parameters, returns a 0-length array (not null). - * - * @return a list of the types of the method's parameters - */ - public Class<?>[] getParameterTypes() - { - if (parameterTypes == null) { - int cnt = vmMethod.getNoArguments(); - ArrayList<Class> list = new ArrayList<Class>(cnt); - for (int i = 0; i < cnt; i++) { - list.add(vmMethod.getArgumentType(i).asClass()); - } - parameterTypes = list; - } - return (Class[])parameterTypes.toArray(new Class[parameterTypes.size()]); - } - - /** - * Get the exception types this method says it throws, in no particular - * order. If the method has no throws clause, returns a 0-length array - * (not null). - * - * @return a list of the types in the method's throws clause - */ - public Class<?>[] getExceptionTypes() - { - if (exceptionTypes == null) { - final VmExceptions exceptions = vmMethod.getExceptions(); - final int cnt = exceptions.getLength(); - final ArrayList<Class> list = new ArrayList<Class>(cnt); - for (int i = 0; i < cnt; i++) { - try - { - list.add(exceptions.getException(i).getResolvedVmClass().asClass()); - } - catch (Exception e) - { - // there is some missing getException(i).getResolvedVmClass() - // if one makes a system.out on the methods it fails, looks "java.lang.Exception" is missing - // I think I'll look into it, if I can. - // 10/03/2005 Martin Husted Hartvig - } - } - exceptionTypes = list; - } - return (Class[])exceptionTypes.toArray(new Class[exceptionTypes.size()]); - } - - /** - * Compare two objects to see if they are semantically equivalent. - * Two Methods are semantically equivalent if they have the same declaring - * class, name, and parameter list. This ignores different exception - * clauses or return types. - * - * @param o the object to compare to - * @return <code>true</code> if they are equal; <code>false</code> if not - */ - public boolean equals(Object o) { - if (!(o instanceof Method)) - return false; - Method that = (Method)o; - if (this.getDeclaringClass() != that.getDeclaringClass()) - return false; - if (!this.getName().equals(that.getName())) - return false; - if (this.getReturnType() != that.getReturnType()) - return false; - if (!Arrays.equals(this.getParameterTypes(), that.getParameterTypes())) - return false; - return true; - } - - /** - * Get the hash code for the Method. The Method hash code is the hash code - * of its name XOR'd with the hash code of its class name. - * - * @return the hash code for the object - */ - public int hashCode() - { - return getDeclaringClass().getName().hashCode() ^ getName().hashCode(); - } - - /** - * Get a String representation of the Method. A Method's String - * representation is "<modifiers> <returntype> - * <methodname>(<paramtypes>) throws <exceptions>", where - * everything after ')' is omitted if there are no exceptions.<br> Example: - * <code>public static int run(java.lang.Runnable,int)</code> - * - * @return the String representation of the Method - */ - public String toString() { - // 128 is a reasonable buffer initial size for constructor - StringBuilder sb = new StringBuilder(128); - sb.append(Modifier.toString(getModifiers())).append(' '); - sb.append(ClassHelper.getUserName(getReturnType())).append(' '); - sb.append(getDeclaringClass().getName()).append('.'); - sb.append(getName()).append('('); - Class[] c = getParameterTypes(); - if (c.length > 0) - { - sb.append(ClassHelper.getUserName(c[0])); - for (int i = 1; i < c.length; i++) - sb.append(',').append(ClassHelper.getUserName(c[i])); - } - sb.append(')'); - c = getExceptionTypes(); - if (c.length > 0) { - sb.append(" throws ").append(c[0].getName()); - for (int i = 1; i < c.length; i++) - sb.append(',').append(c[i].getName()); - } - return sb.toString(); - } - - public String toGenericString() - { - // 128 is a reasonable buffer initial size for constructor - StringBuilder sb = new StringBuilder(128); - sb.append(Modifier.toString(getModifiers())).append(' '); - addTypeParameters(sb, getTypeParameters()); - sb.append(getGenericReturnType()).append(' '); - sb.append(getDeclaringClass().getName()).append('.'); - sb.append(getName()).append('('); - Type[] types = getGenericParameterTypes(); - if (types.length > 0) - { - sb.append(types[0]); - for (int i = 1; i < types.length; i++) - sb.append(',').append(types[i]); - } - sb.append(')'); - types = getGenericExceptionTypes(); - if (types.length > 0) - { - sb.append(" throws ").append(types[0]); - for (int i = 1; i < types.length; i++) - sb.append(',').append(types[i]); - } - return sb.toString(); - } - - /** - * Invoke the method. Arguments are automatically unwrapped and widened, - * and the result is automatically wrapped, if needed.<p> - * - * If the method is static, <code>o</code> will be ignored. Otherwise, - * the method uses dynamic lookup as described in JLS 15.12.4.4. You cannot - * mimic the behavior of nonvirtual lookup (as in super.foo()). This means - * you will get a <code>NullPointerException</code> if <code>o</code> is - * null, and an <code>IllegalArgumentException</code> if it is incompatible - * with the declaring class of the method. If the method takes 0 arguments, - * you may use null or a 0-length array for <code>args</code>.<p> - * - * Next, if this Method enforces access control, your runtime context is - * evaluated, and you may have an <code>IllegalAccessException</code> if - * you could not acces this method in similar compiled code. If the method - * is static, and its class is uninitialized, you trigger class - * initialization, which may end in a - * <code>ExceptionInInitializerError</code>.<p> - * - * Finally, the method is invoked. If it completes normally, the return value - * will be null for a void method, a wrapped object for a primitive return - * method, or the actual return of an Object method. If it completes - * abruptly, the exception is wrapped in an - * <code>InvocationTargetException</code>. - * - * @param o the object to invoke the method on - * @param args the arguments to the method - * @return the return value of the method, wrapped in the appropriate - * wrapper if it is primitive - * @throws IllegalAccessException if the method could not normally be called - * by the Java code (i.e. it is not public) - * @throws IllegalArgumentException if the number of arguments is incorrect; - * if the arguments types are wrong even with a widening conversion; - * or if <code>o</code> is not an instance of the class or interface - * declaring this method - * @throws InvocationTargetException if the method throws an exception - * @throws NullPointerException if <code>o</code> is null and this field - * requires an instance - * @throws ExceptionInInitializerError if accessing a static method triggered - * class initialization, which then failed - */ - public Object invoke(Object o, Object... args) - throws IllegalAccessException, InvocationTargetException { - return VmReflection.invoke(vmMethod, o, args); - } - - /** - * Returns an array of <code>TypeVariable</code> objects that represents - * the type variables declared by this constructor, in declaration order. - * An array of size zero is returned if this class has no type - * variables. - * - * @return the type variables associated with this class. - * @throws GenericSignatureFormatError if the generic signature does - * not conform to the format specified in the Virtual Machine - * specification, version 3. - * @since 1.5 - */ - public TypeVariable<Method>[] getTypeParameters() - { - String sig = getSignature(); - if (sig == null) - return new TypeVariable[0]; - MethodSignatureParser p = new MethodSignatureParser(this, sig); - return p.getTypeParameters(); - } - - /** - * Return the String in the Signature attribute for this method. If there - * is no Signature attribute, return null. - */ - private String getSignature() - { - return vmMethod.getSignature(); - } - - /** - * Returns an array of <code>Type</code> objects that represents - * the exception types declared by this method, in declaration order. - * An array of size zero is returned if this method declares no - * exceptions. - * - * @return the exception types declared by this method. - * @throws GenericSignatureFormatError if the generic signature does - * not conform to the format specified in the Virtual Machine - * specification, version 3. - * @since 1.5 - */ - public Type[] getGenericExceptionTypes() - { - String sig = getSignature(); - if (sig == null) - return getExceptionTypes(); - MethodSignatureParser p = new MethodSignatureParser(this, sig); - return p.getGenericExceptionTypes(); - } - - /** - * Returns an array of <code>Type</code> objects that represents - * the parameter list for this method, in declaration order. - * An array of size zero is returned if this method takes no - * parameters. - * - * @return a list of the types of the method's parameters - * @throws GenericSignatureFormatError if the generic signature does - * not conform to the format specified in the Virtual Machine - * specification, version 3. - * @since 1.5 - */ - public Type[] getGenericParameterTypes() - { - String sig = getSignature(); - if (sig == null) - return getParameterTypes(); - MethodSignatureParser p = new MethodSignatureParser(this, sig); - return p.getGenericParameterTypes(); - } - - /** - * Returns the return type of this method. - * - * @return the return type of this method - * @throws GenericSignatureFormatError if the generic signature does - * not conform to the format specified in the Virtual Machine - * specification, version 3. - * @since 1.5 - */ - public Type getGenericReturnType() - { - String sig = getSignature(); - if (sig == null) - return getReturnType(); - MethodSignatureParser p = new MethodSignatureParser(this, sig); - return p.getGenericReturnType(); - } - /** - * @see java.lang.reflect.AnnotatedElement#getAnnotation(java.lang.Class) - */ - public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { - if(annotationClass.getName().equals(org.jnode.vm.annotation.AllowedPackages.class.getName())) { - return vmMethod.getAnnotation(annotationClass); - } else { - return _getAnnotation(annotationClass); - } - } - - //jnode openjdk - public MethodAccessor getMethodAccessor() { - //todo implement it - throw new UnsupportedOperationException(); - } - - public void setMethodAccessor(MethodAccessor accessor) { - //todo implement it - throw new UnsupportedOperationException(); - } - - public Method copy() { - //todo implement it - throw new UnsupportedOperationException(); - } - - private transient Map<Class, Annotation> declaredAnnotations; - private byte[] annotations; - private byte[] parameterAnnotations; - private byte[] annotationDefault; - - private synchronized Map<Class, Annotation> declaredAnnotations() { - - if (declaredAnnotations == null) { - declaredAnnotations = AnnotationParser.parseAnnotations(annotations, - SharedSecrets.getJavaLangAccess().getConstantPool(getDeclaringClass()), getDeclaringClass()); - } - - return declaredAnnotations; - } - - /** - * If this method is an annotation method, returns the default - * value for the method. If there is no default value, or if the - * method is not a member of an annotation type, returns null. - * Primitive types are wrapped. - * - * @throws TypeNotPresentException if the method returns a Class, - * and the class cannot be found - * - * @since 1.5 - */ - public Object getDefaultValue() { - if (annotationDefault == null) - return null; - - Class memberType = AnnotationType.invocationHandlerReturnType(getReturnType()); - - Object result = AnnotationParser.parseMemberValue(memberType, ByteBuffer.wrap(annotationDefault), - SharedSecrets.getJavaLangAccess().getConstantPool(getDeclaringClass()), getDeclaringClass()); - - if (result instanceof sun.reflect.annotation.ExceptionProxy) - throw new AnnotationFormatError("Invalid default: " + this); - - return result; - } - - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.5 - */ - public <T extends Annotation> T _getAnnotation(Class<T> annotationClass) { - if (annotationClass == null) - throw new NullPointerException(); - - return (T) declaredAnnotations().get(annotationClass); - } - - /** - * @since 1.5 - */ - public Annotation[] getDeclaredAnnotations() { - return declaredAnnotations().values().toArray(EMPTY_ANNOTATION_ARRAY); - } - - private static final Annotation[] EMPTY_ANNOTATION_ARRAY=new Annotation[0]; - - /** - * Returns an array of arrays that represent the annotations on the formal - * parameters, in declaration order, of the method represented by - * this <tt>Method</tt> object. (Returns an array of length zero if the - * underlying method is parameterless. If the method has one or more - * parameters, a nested array of length zero is returned for each parameter - * with no annotations.) The annotation objects contained in the returned - * arrays are serializable. The caller of this method is free to modify - * the returned arrays; it will have no effect on the arrays returned to - * other callers. - * - * @return an array of arrays that represent the annotations on the formal - * parameters, in declaration order, of the method represented by this - * Method object - * @since 1.5 - */ - public Annotation[][] getParameterAnnotations() { - - int numParameters = vmMethod.getNoArguments(); - - if (parameterAnnotations == null) - return new Annotation[numParameters][0]; - - Annotation[][] result = AnnotationParser.parseParameterAnnotations(parameterAnnotations, - SharedSecrets.getJavaLangAccess().getConstantPool(getDeclaringClass()), getDeclaringClass()); - - if (result.length != numParameters) - throw new AnnotationFormatError("Parameter annotations don't match number of parameters"); - - return result; - } - - static <X extends GenericDeclaration> - void addTypeParameters(StringBuilder sb, TypeVariable<X>[] typeArgs) - { - if (typeArgs.length == 0) - return; - sb.append('<'); - for (int i = 0; i < typeArgs.length; ++i) - { - if (i > 0) - sb.append(','); - sb.append(typeArgs[i]); - } - sb.append("> "); - } -} Modified: trunk/core/src/core/org/jnode/vm/classmgr/VmMethod.java =================================================================== --- trunk/core/src/core/org/jnode/vm/classmgr/VmMethod.java 2008-12-17 13:58:56 UTC (rev 4793) +++ trunk/core/src/core/org/jnode/vm/classmgr/VmMethod.java 2008-12-18 18:34:56 UTC (rev 4794) @@ -193,44 +193,46 @@ } Member javaMember = javaMemberHolder.get(); if (javaMember == null) { - if (isConstructor()) { - //parameter types - int arg_count = getNoArguments(); - Class[] args = new Class[arg_count]; - for (int i = 0; i < arg_count; i++) { - args[i] = getArgumentType(i).asClass(); + //parameter types + int arg_count = getNoArguments(); + Class[] args = new Class[arg_count]; + for (int i = 0; i < arg_count; i++) { + args[i] = getArgumentType(i).asClass(); + } + //checked exceptions + final VmExceptions exceptions = getExceptions(); + int ce_count = exceptions.getLength(); + final Class[] ces = new Class[ce_count]; + for (int i = 0; i < ce_count; i++) { + VmConstClass vmConstClass = exceptions.getException(i); + if (!vmConstClass.isResolved()) { + vmConstClass.doResolve(getDeclaringClass().getLoader()); } - - //checked exceptions - final VmExceptions exceptions = getExceptions(); - int ce_count = exceptions.getLength(); - final Class[] ces = new Class[ce_count]; - for (int i = 0; i < ce_count; i++) { - VmConstClass vmConstClass = exceptions.getException(i); - if (!vmConstClass.isResolved()) { - vmConstClass.doResolve(getDeclaringClass().getLoader()); - } - ces[i] = vmConstClass.getResolvedVmClass().asClass(); + ces[i] = vmConstClass.getResolvedVmClass().asClass(); + } + //slot + VmType decl_type = getDeclaringClass(); + int slot = -1; + for (int i = 0; i < decl_type.getNoDeclaredMethods(); i++) { + if (this == decl_type.getDeclaredMethod(i)) { + slot = i; + break; } + } - //slot - VmType decl_type = getDeclaringClass(); - int slot = -1; - for (int i = 0; i < decl_type.getNoDeclaredMethods(); i++) { - if (this == decl_type.getDeclaredMethod(i)) { - slot = i; - break; - } - } - + if (isConstructor()) { if (slot == -1) { throw new ClassFormatError("Invalid constructor"); } - javaMember = new Constructor(getDeclaringClass().asClass(), args, ces, getModifiers(), slot, getSignature(), getRawAnnotations(), getRawParameterAnnotations()); } else { - javaMember = new Method(this); + if (slot == -1) { + throw new ClassFormatError("Invalid method"); + } + javaMember = new Method(getDeclaringClass().asClass(), getName(), args, getReturnType().asClass(), ces, + getModifiers(), slot, getSignature(), getRawAnnotations(), getRawParameterAnnotations(), + getRawAnnotationDefault()); } javaMemberHolder.set(javaMember); } Modified: trunk/core/src/core/org/jnode/vm/isolate/VmIsolate.java =================================================================== --- trunk/core/src/core/org/jnode/vm/isolate/VmIsolate.java 2008-12-17 13:58:56 UTC (rev 4793) +++ trunk/core/src/core/org/jnode/vm/isolate/VmIsolate.java 2008-12-18 18:34:56 UTC (rev 4794) @@ -981,6 +981,7 @@ //add to parent this.creator.addChild(this); + mainMethod.setAccessible(true); // Run main method. mainMethod.invoke(null, new Object[]{args}); } catch (Throwable ex) { Added: trunk/core/src/openjdk/java/java/lang/reflect/Method.java =================================================================== --- trunk/core/src/openjdk/java/java/lang/reflect/Method.java (rev 0) +++ trunk/core/src/openjdk/java/java/lang/reflect/Method.java 2008-12-18 18:34:56 UTC (rev 4794) @@ -0,0 +1,788 @@ +/* + * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.lang.reflect; + +import sun.reflect.MethodAccessor; +import sun.reflect.Reflection; +import sun.reflect.generics.repository.MethodRepository; +import sun.reflect.generics.factory.CoreReflectionFactory; +import sun.reflect.generics.factory.GenericsFactory; +import sun.reflect.generics.scope.MethodScope; +import sun.reflect.annotation.AnnotationType; +import sun.reflect.annotation.AnnotationParser; +import java.lang.annotation.Annotation; +import java.lang.annotation.AnnotationFormatError; +import java.nio.ByteBuffer; +import java.util.Map; + +/** + * A {@code Method} provides information about, and access to, a single method + * on a class or interface. The reflected method may be a class method + * or an instance method (including an abstract method). + * + * <p>A {@code Method} permits widening conversions to occur when matching the + * actual parameters to invoke with the underlying method's formal + * parameters, but it throws an {@code IllegalArgumentException} if a + * narrowing conversion would occur. + * + * @see Member + * @see java.lang.Class + * @see java.lang.Class#getMethods() + * @see java.lang.Class#getMethod(String, Class[]) + * @see java.lang.Class#getDeclaredMethods() + * @see java.lang.Class#getDeclaredMethod(String, Class[]) + * + * @author Kenneth Russell + * @author Nakul Saraiya + */ +public final + class Method extends AccessibleObject implements GenericDeclaration, + Member { + private Class clazz; + private int slot; + // This is guaranteed to be interned by the VM in the 1.4 + // reflection implementation + private String name; + private Class returnType; + private Class[] parameterTypes; + private Class[] exceptionTypes; + private int modifiers; + // Generics and annotations support + private transient String signature; + // generic info repository; lazily initialized + private transient MethodRepository genericInfo; + private byte[] annotations; + private byte[] parameterAnnotations; + private byte[] annotationDefault; + private volatile MethodAccessor methodAccessor; + // For sharing of MethodAccessors. This branching structure is + // currently only two levels deep (i.e., one root Method and + // potentially many Method objects pointing to it.) + private Method root; + + // More complicated security check cache needed here than for + // Class.newInstance() and Constructor.newInstance() + private Class securityCheckCache; + private Class securityCheckTargetClassCache; + + // Modifiers that can be applied to a method in source code + private static final int LANGUAGE_MODIFIERS = + Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | + Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | + Modifier.SYNCHRONIZED | Modifier.NATIVE; + + // Generics infrastructure + + private String getGenericSignature() {return signature;} + + // Accessor for factory + private GenericsFactory getFactory() { + // create scope and factory + return CoreReflectionFactory.make(this, MethodScope.make(this)); + } + + // Accessor for generic info repository + private MethodRepository getGenericInfo() { + // lazily initialize repository if necessary + if (genericInfo == null) { + // create and cache generic info repository + genericInfo = MethodRepository.make(getGenericSignature(), + getFactory()); + } + return genericInfo; //return cached repository + } + + //jnode + /** + * Package-private constructor used by ReflectAccess to enable + * instantiation of these objects in Java code from the java.lang + * package via sun.reflect.LangReflectAccess. + */ + public Method(Class declaringClass, + String name, + Class[] parameterTypes, + Class returnType, + Class[] checkedExceptions, + int modifiers, + int slot, + String signature, + byte[] annotations, + byte[] parameterAnnotations, + byte[] annotationDefault) + { + this.clazz = declaringClass; + this.name = name; + this.parameterTypes = parameterTypes; + this.returnType = returnType; + this.exceptionTypes = checkedExceptions; + this.modifiers = modifiers; + this.slot = slot; + this.signature = signature; + this.annotations = annotations; + this.parameterAnnotations = parameterAnnotations; + this.annotationDefault = annotationDefault; + } + + /** + * Package-private routine (exposed to java.lang.Class via + * ReflectAccess) which returns a copy of this Method. The copy's + * "root" field points to this Method. + */ + Method copy() { + // This routine enables sharing of MethodAccessor objects + // among Method objects which refer to the same underlying + // method in the VM. (All of this contortion is only necessary + // because of the "accessibility" bit in AccessibleObject, + // which implicitly requires that new java.lang.reflect + // objects be fabricated for each reflective call on Class + // objects.) + Method res = new Method(clazz, name, parameterTypes, returnType, + exceptionTypes, modifiers, slot, signature, + annotations, parameterAnnotations, annotationDefault); + res.root = this; + // Might as well eagerly propagate this if already present + res.methodAccessor = methodAccessor; + return res; + } + + /** + * Returns the {@code Class} object representing the class or interface + * that declares the method represented by this {@code Method} object. + */ + public Class<?> getDeclaringClass() { + return clazz; + } + + /** + * Returns the name of the method represented by this {@code Method} + * object, as a {@code String}. + */ + public String getName() { + return name; + } + + /** + * Returns the Java language modifiers for the method represented + * by this {@code Method} object, as an integer. The {@code Modifier} class should + * be used to decode the modifiers. + * + * @see Modifier + */ + public int getModifiers() { + return modifiers; + } + + /** + * Returns an array of {@code TypeVariable} objects that represent the + * type variables declared by the generic declaration represented by this + * {@code GenericDeclaration} object, in declaration order. Returns an + * array of length 0 if the underlying generic declaration declares no type + * variables. + * + * @return an array of {@code TypeVariable} objects that represent + * the type variables declared by this generic declaration + * @throws GenericSignatureFormatError if the generic + * signature of this generic declaration does not conform to + * the format specified in the Java Virtual Machine Specification, + * 3rd edition + * @since 1.5 + */ + public TypeVariable<Method>[] getTypeParameters() { + if (getGenericSignature() != null) + return (TypeVariable<Method>[])getGenericInfo().getTypeParameters(); + else + return (TypeVariable<Method>[])new TypeVariable[0]; + } + + /** + * Returns a {@code Class} object that represents the formal return type + * of the method represented by this {@code Method} object. + * + * @return the return type for the method this object represents + */ + public Class<?> getReturnType() { + return returnType; + } + + /** + * Returns a {@code Type} object that represents the formal return + * type of the method represented by this {@code Method} object. + * + * <p>If the return type is a parameterized type, + * the {@code Type} object returned must accurately reflect + * the actual type parameters used in the source code. + * + * <p>If the return type is a type variable or a parameterized type, it + * is created. Otherwise, it is resolved. + * + * @return a {@code Type} object that represents the formal return + * type of the underlying method + * @throws GenericSignatureFormatError + * if the generic method signature does not conform to the format + * specified in the Java Virtual Machine Specification, 3rd edition + * @throws TypeNotPresentException if the underlying method's + * return type refers to a non-existent type declaration + * @throws MalformedParameterizedTypeException if the + * underlying method's return typed refers to a parameterized + * type that cannot be instantiated for any reason + * @since 1.5 + */ + public Type getGenericReturnType() { + if (getGenericSignature() != null) { + return getGenericInfo().getReturnType(); + } else { return getReturnType();} + } + + + /** + * Returns an array of {@code Class} objects that represent the formal + * parameter types, in declaration order, of the method + * represented by this {@code Method} object. Returns an array of length + * 0 if the underlying method takes no parameters. + * + * @return the parameter types for the method this object + * represents + */ + public Class<?>[] getParameterTypes() { + return (Class<?>[]) parameterTypes.clone(); + } + + /** + * Returns an array of {@code Type} objects that represent the formal + * parameter types, in declaration order, of the method represented by + * this {@code Method} object. Returns an array of length 0 if the + * underlying method takes no parameters. + * + * <p>If a formal parameter type is a parameterized type, + * the {@code Type} object returned for it must accurately reflect + * the actual type parameters used in the source code. + * + * <p>If a formal parameter type is a type variable or a parameterized + * type, it is created. Otherwise, it is resolved. + * + * @return an array of Types that represent the formal + * parameter types of the underlying method, in declaration order + * @throws GenericSignatureFormatError + * if the generic method signature does not conform to the format + * specified in the Java Virtual Machine Specification, 3rd edition + * @throws TypeNotPresentException if any of the parameter + * types of the underlying method refers to a non-existent type + * declaration + * @throws MalformedParameterizedTypeException if any of + * the underlying method's parameter types refer to a parameterized + * type that cannot be instantiated for any reason + * @since 1.5 + */ + public Type[] getGenericParameterTypes() { + if (getGenericSignature() != null) + return getGenericInfo().getParameterTypes(); + else + return getParameterTypes(); + } + + + /** + * Returns an array of {@code Class} objects that represent + * the types of the exceptions declared to be thrown + * by the underlying method + * represented by this {@code Method} object. Returns an array of length + * 0 if the method declares no exceptions in its {@code throws} clause. + * + * @return the exception types declared as being thrown by the + * method this object represents + */ + public Class<?>[] getExceptionTypes() { + return (Class<?>[]) exceptionTypes.clone(); + } + + /** + * Returns an array of {@code Type} objects that represent the + * exceptions declared to be thrown by this {@code Method} object. + * Returns an array of length 0 if the underlying method declares + * no exceptions in its {@code throws} clause. + * + * <p>If an exception type is a parameterized type, the {@code Type} + * object returned for it must accurately reflect the actual type + * parameters used in the source code. + * + * <p>If an exception type is a type variable or a parameterized + * type, it is created. Otherwise, it is resolved. + * + * @return an array of Types that represent the exception types + * thrown by the underlying method + * @throws GenericSignatureFormatError + * if the generic method signature does not conform to the format + * specified in the Java Virtual Machine Specification, 3rd edition + * @throws TypeNotPresentException if the underlying method's + * {@code throws} clause refers to a non-existent type declaration + * @throws MalformedParameterizedTypeException if + * the underlying method's {@code throws} clause refers to a + * parameterized type that cannot be instantiated for any reason + * @since 1.5 + */ + public Type[] getGenericExceptionTypes() { + Type[] result; + if (getGenericSignature() != null && + ((result = getGenericInfo().getExceptionTypes()).length > 0)) + return result; + else + return getExceptionTypes(); + } + + /** + * Compares this {@code Method} against the specified object. Returns + * true if the objects are the same. Two {@code Methods} are the same if + * they were declared by the same class and have the same name + * and formal parameter types and return type. + */ + public boolean equals(Object obj) { + if (obj != null && obj instanceof Method) { + Method other = (Method)obj; + if ((getDeclaringClass() == other.getDeclaringClass()) + && (getName() == other.getName())) { + if (!returnType.equals(other.getReturnType())) + return false; + /* Avoid unnecessary cloning */ + Class[] params1 = parameterTypes; + Class[] params2 = other.parameterTypes; + if (params1.length == params2.length) { + for (int i = 0; i < params1.length; i++) { + if (params1[i] != params2[i]) + return false; + } + return true; + } + } + } + return false; + } + + /** + * Returns a hashcode for this {@code Method}. The hashcode is computed + * as the exclusive-or of the hashcodes for the underlying + * method's declaring class name and the method's name. + */ + public int hashCode() { + return getDeclaringClass().getName().hashCode() ^ getName().hashCode(); + } + + /** + * Returns a string describing this {@code Method}. The string is + * formatted as the method access modifiers, if any, followed by + * the method return type, followed by a space, followed by the + * class declaring the method, followed by a period, followed by + * the method name, followed by a parenthesized, comma-separated + * list of the method's formal parameter types. If the method + * throws checked exceptions, the parameter list is followed by a + * space, followed by the word throws followed by a + * comma-separated list of the thrown exception types. + * For example: + * <pre> + * public boolean java.lang.Object.equals(java.lang.Object) + * </pre> + * + * <p>The access modifiers are placed in canonical order as + * specified by "The Java Language Specification". This is + * {@code public}, {@code protected} or {@code private} first, + * and then other modifiers in the following order: + * {@code abstract}, {@code static}, {@code final}, + * {@code synchronized}, {@code native}. + */ + public String toString() { + try { + StringBuffer sb = new StringBuffer(); + int mod = getModifiers() & LANGUAGE_MODIFIERS; + if (mod != 0) { + sb.append(Modifier.toString(mod) + " "); + } + sb.append(Field.getTypeName(getReturnType()) + " "); + sb.append(Field.getTypeName(getDeclaringClass()) + "."); + sb.append(getName() + "("); + Class[] params = parameterTypes; // avoid clone + for (int j = 0; j < params.length; j++) { + sb.append(Field.getTypeName(params[j])); + if (j < (params.length - 1)) + sb.append(","); + } + sb.append(")"); + Class[] exceptions = exceptionTypes; // avoid clone + if (exceptions.length > 0) { + sb.append(" throws "); + for (int k = 0; k < exceptions.length; k++) { + sb.append(exceptions[k].getName()); + if (k < (exceptions.length - 1)) + sb.append(","); + } + } + return sb.toString(); + } catch (Exception e) { + return "<" + e + ">"; + } + } + + /** + * Returns a string describing this {@code Method}, including + * type parameters. The string is formatted as the method access + * modifiers, if any, followed by an angle-bracketed + * comma-separated list of the method's type parameters, if any, + * followed by the method's generic return type, followed by a + * space, followed by the class declaring the method, followed by + * a period, followed by the method name, followed by a + * parenthesized, comma-separated list of the method's generic + * formal parameter types. + * + * A space is used to separate access modifiers from one another + * and from the type parameters or return type. If there are no + * type parameters, the type parameter list is elided; if the type + * parameter list is present, a space separates the list from the + * class name. If the method is declared to throw exceptions, the + * parameter list is followed by a space, followed by the word + * throws followed by a comma-separated list of the generic thrown + * exception types. If there are no type parameters, the type + * parameter list is elided. + * + * <p>The access modifiers are placed in canonical order as + * specified by "The Java Language Specification". This is + * {@code public}, {@code protected} or {@code private} first, + * and then other modifiers in the following order: + * {@code abstract}, {@code static}, {@code final}, + * {@code synchronized} {@code native}. + * + * @return a string describing this {@code Method}, + * include type parameters + * + * @since 1.5 + */ + public String toGenericString() { + try { + StringBuilder sb = new StringBuilder(); + int mod = getModifiers() & LANGUAGE_MODIFIERS; + if (mod != 0) { + sb.append(Modifier.toString(mod) + " "); + } + TypeVariable<?>[] typeparms = getTypeParameters(); + if (typeparms.length > 0) { + boolean first = true; + sb.append("<"); + for(TypeVariable<?> typeparm: typeparms) { + if (!first) + sb.append(","); + // Class objects can't occur here; no need to test + // and call Class.getName(). + sb.append(typeparm.toString()); + first = false; + } + sb.append("> "); + } + + Type genRetType = getGenericReturnType(); + sb.append( ((genRetType instanceof Class<?>)? + Field.getTypeName((Class<?>)genRetType):genRetType.toString()) + " "); + + sb.append(Field.getTypeName(getDeclaringClass()) + "."); + sb.append(getName() + "("); + Type[] params = getGenericParameterTypes(); + for (int j = 0; j < params.length; j++) { + String param = (params[j] instanceof Class)? + Field.getTypeName((Class)params[j]): + (params[j].toString()); + sb.append(param); + if (j < (params.length - 1)) + sb.append(","); + } + sb.append(")"); + Type[] exceptions = getGenericExceptionTypes(); + if (exceptions.length > 0) { + sb.append(" throws "); + for (int k = 0; k < exceptions.length; k++) { + sb.append((exceptions[k] instanceof Class)? + ((Class)exceptions[k]).getName(): + exceptions[k].toString()); + if (k < (exceptions.length - 1)) + sb.append(","); + } + } + return sb.toString(); + } catch (Exception e) { + return "<" + e + ">"; + } + } + + /** + * Invokes the underlying method represented by this {@code Method} + * object, on the specified object with the specified parameters. + * Individual parameters are automatically unwrapped to match + * primitive formal parameters, and both primitive and reference + * parameters are subject to method invocation conversions as + * necessary. + * + * <p>If the underlying method is static, then the specified {@code obj} + * argument is ignored. It may be null. + * + * <p>If the number of formal parameters required by the underlying method is + * 0, the supplied {@code args} array may be of length 0 or null. + * + * <p>If the underlying method is an instance method, it is invoked + * using dynamic method lookup as documented in The Java Language + * Specification, Second Edition, section 15.12.4.4; in particular, + * overriding based on the runtime type of the target object will occur. + * + * <p>If the underlying method is static, the class that declared + * the method is initialized if it has not already been initialized. + * + * <p>If the method completes normally, the value it returns is + * returned to the caller of invoke; if the value has a primitive + * type, it is first appropriately wrapped in an object. However, + * if the value has the type of an array of a primitive type, the + * elements of the array are <i>not</i> wrapped in objects; in + * other words, an array of primitive type is returned. If the + * underlying method return type is void, the invocation returns + * null. + * + * @param obj the object the underlying method is invoked from + * @param args the arguments used for the method call + * @return the result of dispatching the method represented by + * this object on {@code obj} with parameters + * {@code args} + * + * @exception IllegalAccessException if this {@code Method} object + * enforces Java language access control and the underlying + * method is inaccessible. + * @exception IllegalArgumentException if the method is an + * instance method and the specified object argument + * is not an instance of the class or interface + * declaring the underlying method (or of a subclass + * or implementor thereof); if the number of actual + * and formal parameters differ; if an unwrapping + * conversion for primitive arguments fails; or if, + * after possible unwrapping, a parameter value + * cannot be converted to the corresponding formal + * parameter type by a method invocation conversion. + * @exception InvocationTargetException if the underlying method + * throws an exception. + * @exception NullPointerException if the specified object is null + * and the method is an instance method. + * @exception ExceptionInInitializerError if the initialization + * provoked by this method fails. + */ + public Object invoke(Object obj, Object... args) + throws IllegalAccessException, IllegalArgumentException, + InvocationTargetException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(1); + Class targetClass = ((obj == null || !Modifier.isProtected(modifiers)) + ? clazz + : obj.getClass()); + + boolean cached; + synchronized (this) { + cached = (securityCheckCache == caller) + && (securityCheckTargetClassCache == targetClass); + } + if (!cached) { + Reflection.ensureMemberAccess(caller, clazz, obj, modifiers); + synchronized (this) { + securityCheckCache = caller; + securityCheckTargetClassCache = targetClass; + } + } + } + } + if (methodAccessor == null) acquireMethodAccessor(); + return methodAccessor.invoke(obj, args); + } + + /** + * Returns {@code true} if this method is a bridge + * method; returns {@code false} otherwise. + * + * @return true if and only if this method is a bridge + * method as defined by the Java Language Specification. + * @since 1.5 + */ + public boolean isBridge() { + return (getModifiers() & Modifier.BRIDGE) != 0; + } + + /** + * Returns {@code true} if this method was declared to take + * a variable number of arguments; returns {@code false} + * otherwise. + * + * @return {@code true} if an only if this method was declared to + * take a variable number of arguments. + * @since 1.5 + */ + public boolean isVarArgs() { + return (getModifiers() & Modifier.VARARGS) != 0; + } + + /** + * Returns {@code true} if this method is a synthetic + * method; returns {@code false} otherwise. + * + * @return true if and only if this method is a synthetic + * method as defined by the Java Language Specification. + * @since 1.5 + */ + public boolean isSynthetic() { + return Modifier.isSynthetic(getModifiers()); + } + + // NOTE that there is no synchronization used here. It is correct + // (though not efficient) to generate more than one MethodAccessor + // for a given Method. However, avoiding synchronization will + // probably make the implementation more scalable. + private void acquireMethodAccessor() { + // First check to see if one has been created yet, and take it + // if so + MethodAccessor tmp = null; + if (root != null) tmp = root.getMethodAccessor(); + if (tmp != null) { + methodAccessor = tmp; + return; + } + // Otherwise fabricate one and propagate it up to the root + tmp = reflectionFactory.newMethodAccessor(this); + setMethodAccessor(tmp); + } + + // Returns MethodAccessor for this Method object, not looking up + // the chain to the root + MethodAccessor getMethodAccessor() { + return methodAccessor; + } + + // Sets the MethodAcce... [truncated message content] |