diff options
Diffstat (limited to 'openjdk/java/lang')
32 files changed, 0 insertions, 24010 deletions
diff --git a/openjdk/java/lang/Class.java b/openjdk/java/lang/Class.java deleted file mode 100644 index 07fd7bd5..00000000 --- a/openjdk/java/lang/Class.java +++ /dev/null @@ -1,3601 +0,0 @@ -/* - * Copyright (c) 1994, 2013, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang; - -import java.lang.reflect.AnnotatedElement; -import java.lang.reflect.Array; -import java.lang.reflect.GenericArrayType; -import java.lang.reflect.GenericDeclaration; -import java.lang.reflect.Member; -import java.lang.reflect.Field; -import java.lang.reflect.Executable; -import java.lang.reflect.Method; -import java.lang.reflect.Constructor; -import java.lang.reflect.Modifier; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.AnnotatedType; -import java.lang.ref.SoftReference; -import java.io.InputStream; -import java.io.ObjectStreamField; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Set; -import java.util.Map; -import java.util.HashMap; -import java.util.Objects; -import sun.misc.Unsafe; -import sun.reflect.CallerSensitive; -import sun.reflect.ConstantPool; -import sun.reflect.Reflection; -import sun.reflect.ReflectionFactory; -import sun.reflect.generics.factory.CoreReflectionFactory; -import sun.reflect.generics.factory.GenericsFactory; -import sun.reflect.generics.repository.ClassRepository; -import sun.reflect.generics.repository.MethodRepository; -import sun.reflect.generics.repository.ConstructorRepository; -import sun.reflect.generics.scope.ClassScope; -import sun.security.util.SecurityConstants; -import java.lang.annotation.Annotation; -import java.lang.reflect.Proxy; -import sun.reflect.annotation.*; -import sun.reflect.misc.ReflectUtil; -import cli.System.Runtime.Serialization.IObjectReference; -import cli.System.Runtime.Serialization.SerializationException; -import cli.System.Runtime.Serialization.SerializationInfo; -import cli.System.Runtime.Serialization.StreamingContext; - -@cli.System.SerializableAttribute.Annotation -final class ClassSerializationProxy implements IObjectReference -{ - private cli.System.Type type; - private String sig; - - @cli.System.Security.SecurityCriticalAttribute.Annotation - public Object GetRealObject(StreamingContext context) - { - if (sig != null) - { - if (sig.length() == 1) - { - switch (sig.charAt(0)) - { - case 'B': - return Byte.TYPE; - case 'C': - return Character.TYPE; - case 'D': - return Double.TYPE; - case 'F': - return Float.TYPE; - case 'I': - return Integer.TYPE; - case 'J': - return Long.TYPE; - case 'S': - return Short.TYPE; - case 'Z': - return Boolean.TYPE; - case 'V': - return Void.TYPE; - } - } - String className; - if (sig.charAt(0) == 'L') - { - className = sig.substring(1, sig.length() - 1); - } - else - { - className = sig; - } - try - { - return Class.forName(className, false, Thread.currentThread().getContextClassLoader()); - } - catch (ClassNotFoundException x) - { - ikvm.runtime.Util.throwException(new SerializationException(x.getMessage(), x)); - } - } - return ikvm.runtime.Util.getClassFromTypeHandle(type.get_TypeHandle()); - } -} - -/** - * Instances of the class {@code Class} represent classes and - * interfaces in a running Java application. An enum is a kind of - * class and an annotation is a kind of interface. Every array also - * belongs to a class that is reflected as a {@code Class} object - * that is shared by all arrays with the same element type and number - * of dimensions. The primitive Java types ({@code boolean}, - * {@code byte}, {@code char}, {@code short}, - * {@code int}, {@code long}, {@code float}, and - * {@code double}), and the keyword {@code void} are also - * represented as {@code Class} objects. - * - * <p> {@code Class} has no public constructor. Instead {@code Class} - * objects are constructed automatically by the Java Virtual Machine as classes - * are loaded and by calls to the {@code defineClass} method in the class - * loader. - * - * <p> The following example uses a {@code Class} object to print the - * class name of an object: - * - * <blockquote><pre> - * void printClassName(Object obj) { - * System.out.println("The class of " + obj + - * " is " + obj.getClass().getName()); - * } - * </pre></blockquote> - * - * <p> It is also possible to get the {@code Class} object for a named - * type (or for void) using a class literal. See Section 15.8.2 of - * <cite>The Java™ Language Specification</cite>. - * For example: - * - * <blockquote> - * {@code System.out.println("The name of class Foo is: "+Foo.class.getName());} - * </blockquote> - * - * @param <T> the type of the class modeled by this {@code Class} - * object. For example, the type of {@code String.class} is {@code - * Class<String>}. Use {@code Class<?>} if the class being modeled is - * unknown. - * - * @author unascribed - * @see java.lang.ClassLoader#defineClass(byte[], int, int) - * @since JDK1.0 - */ -@cli.System.SerializableAttribute.Annotation -public final class Class<T> implements java.io.Serializable, - GenericDeclaration, - Type, - AnnotatedElement { - private static final int ANNOTATION= 0x00002000; - private static final int ENUM = 0x00004000; - private static final int SYNTHETIC = 0x00001000; - - // [IKVM] additional fields - java.security.ProtectionDomain pd; - Object[] signers; - - // For types that live in a static .NET assembly (i.e. ikvmc compiled or .NET types) - // this field contains the type (used for .NET serialization of Class objects). - // This field is also used by fast class literals to remember the type that can then - // lazily be resolved to the corresponding TypeWrapper. - // For dynamically loaded classes and primitives it is null. - final cli.System.Type type; - - /* - * Constructor. Only the Java Virtual Machine creates Class - * objects. - */ - private Class() - { - // this constructor is not used, but exists for compatibility - // (otherwise it would look as if this class doesn't have a constructor, which might break some code) - throw new InternalError(); - } - - @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation - Class(cli.System.Type type) - { - this.type = type; - } - - // We use custom serialization, because we want to deserialize a via proxy that properly resolves the Class singletons. - // Note that we don't implement ISerializable in this source, but in map.xml to avoid it being visible to Java code. - // We don't have a security demand, because the information exposed is harmless. - @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation - @cli.System.Security.SecurityCriticalAttribute.Annotation - public void GetObjectData(SerializationInfo info, StreamingContext context) - { - info.AddValue("type", type); - info.AddValue("sig", type == null ? getSigName() : null); - info.SetType(ikvm.runtime.Util.getInstanceTypeFromClass(ClassSerializationProxy.class)); - } - - private native String getSigName(); - - // [IKVM] this provides an implicit conversion operator from System.Type to java.lang.Class - @cli.System.Runtime.CompilerServices.SpecialNameAttribute.Annotation - @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation - public static Class op_Implicit(cli.System.Type type) - { - return ikvm.runtime.Util.getFriendlyClassFromType(type); - } - - /** - * Converts the object to a string. The string representation is the - * string "class" or "interface", followed by a space, and then by the - * fully qualified name of the class in the format returned by - * {@code getName}. If this {@code Class} object represents a - * primitive type, this method returns the name of the primitive type. If - * this {@code Class} object represents void this method returns - * "void". - * - * @return a string representation of this class object. - */ - public String toString() { - return (isInterface() ? "interface " : (isPrimitive() ? "" : "class ")) - + getName(); - } - - /** - * Returns a string describing this {@code Class}, including - * information about modifiers and type parameters. - * - * The string is formatted as a list of type modifiers, if any, - * followed by the kind of type (empty string for primitive types - * and {@code class}, {@code enum}, {@code interface}, or - * <code>@</code>{@code interface}, as appropriate), followed - * by the type's name, followed by an angle-bracketed - * comma-separated list of the type's type parameters, if any. - * - * A space is used to separate modifiers from one another and to - * separate any modifiers from the kind of type. The modifiers - * occur in canonical order. If there are no type parameters, the - * type parameter list is elided. - * - * <p>Note that since information about the runtime representation - * of a type is being generated, modifiers not present on the - * originating source code or illegal on the originating source - * code may be present. - * - * @return a string describing this {@code Class}, including - * information about modifiers and type parameters - * - * @since 1.8 - */ - public String toGenericString() { - if (isPrimitive()) { - return toString(); - } else { - StringBuilder sb = new StringBuilder(); - - // Class modifiers are a superset of interface modifiers - int modifiers = getModifiers() & Modifier.classModifiers(); - if (modifiers != 0) { - sb.append(Modifier.toString(modifiers)); - sb.append(' '); - } - - if (isAnnotation()) { - sb.append('@'); - } - if (isInterface()) { // Note: all annotation types are interfaces - sb.append("interface"); - } else { - if (isEnum()) - sb.append("enum"); - else - sb.append("class"); - } - sb.append(' '); - sb.append(getName()); - - TypeVariable<?>[] typeparms = getTypeParameters(); - if (typeparms.length > 0) { - boolean first = true; - sb.append('<'); - for(TypeVariable<?> typeparm: typeparms) { - if (!first) - sb.append(','); - sb.append(typeparm.getTypeName()); - first = false; - } - sb.append('>'); - } - - return sb.toString(); - } - } - - /** - * Returns the {@code Class} object associated with the class or - * interface with the given string name. Invoking this method is - * equivalent to: - * - * <blockquote> - * {@code Class.forName(className, true, currentLoader)} - * </blockquote> - * - * where {@code currentLoader} denotes the defining class loader of - * the current class. - * - * <p> For example, the following code fragment returns the - * runtime {@code Class} descriptor for the class named - * {@code java.lang.Thread}: - * - * <blockquote> - * {@code Class t = Class.forName("java.lang.Thread")} - * </blockquote> - * <p> - * A call to {@code forName("X")} causes the class named - * {@code X} to be initialized. - * - * @param className the fully qualified name of the desired class. - * @return the {@code Class} object for the class with the - * specified name. - * @exception LinkageError if the linkage fails - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails - * @exception ClassNotFoundException if the class cannot be located - */ - @CallerSensitive - public static Class<?> forName(String className) - throws ClassNotFoundException { - return forName0(className, true, - ClassLoader.getClassLoader(Reflection.getCallerClass())); - } - - - /** - * Returns the {@code Class} object associated with the class or - * interface with the given string name, using the given class loader. - * Given the fully qualified name for a class or interface (in the same - * format returned by {@code getName}) this method attempts to - * locate, load, and link the class or interface. The specified class - * loader is used to load the class or interface. If the parameter - * {@code loader} is null, the class is loaded through the bootstrap - * class loader. The class is initialized only if the - * {@code initialize} parameter is {@code true} and if it has - * not been initialized earlier. - * - * <p> If {@code name} denotes a primitive type or void, an attempt - * will be made to locate a user-defined class in the unnamed package whose - * name is {@code name}. Therefore, this method cannot be used to - * obtain any of the {@code Class} objects representing primitive - * types or void. - * - * <p> If {@code name} denotes an array class, the component type of - * the array class is loaded but not initialized. - * - * <p> For example, in an instance method the expression: - * - * <blockquote> - * {@code Class.forName("Foo")} - * </blockquote> - * - * is equivalent to: - * - * <blockquote> - * {@code Class.forName("Foo", true, this.getClass().getClassLoader())} - * </blockquote> - * - * Note that this method throws errors related to loading, linking or - * initializing as specified in Sections 12.2, 12.3 and 12.4 of <em>The - * Java Language Specification</em>. - * Note that this method does not check whether the requested class - * is accessible to its caller. - * - * <p> If the {@code loader} is {@code null}, and a security - * manager is present, and the caller's class loader is not null, then this - * method calls the security manager's {@code checkPermission} method - * with a {@code RuntimePermission("getClassLoader")} permission to - * ensure it's ok to access the bootstrap class loader. - * - * @param name fully qualified name of the desired class - * @param initialize if {@code true} the class will be initialized. - * See Section 12.4 of <em>The Java Language Specification</em>. - * @param loader class loader from which the class must be loaded - * @return class object representing the desired class - * - * @exception LinkageError if the linkage fails - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails - * @exception ClassNotFoundException if the class cannot be located by - * the specified class loader - * - * @see java.lang.Class#forName(String) - * @see java.lang.ClassLoader - * @since 1.2 - */ - @CallerSensitive - public static Class<?> forName(String name, boolean initialize, - ClassLoader loader) - throws ClassNotFoundException - { - if (sun.misc.VM.isSystemDomainLoader(loader)) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - ClassLoader ccl = ClassLoader.getClassLoader(Reflection.getCallerClass()); - if (!sun.misc.VM.isSystemDomainLoader(ccl)) { - sm.checkPermission( - SecurityConstants.GET_CLASSLOADER_PERMISSION); - } - } - } - return forName0(name, initialize, loader); - } - - /** Called after security checks have been made. */ - private static native Class<?> forName0(String name, boolean initialize, - ClassLoader loader) - throws ClassNotFoundException; - - /** - * Creates a new instance of the class represented by this {@code Class} - * object. The class is instantiated as if by a {@code new} - * expression with an empty argument list. The class is initialized if it - * has not already been initialized. - * - * <p>Note that this method propagates any exception thrown by the - * nullary constructor, including a checked exception. Use of - * this method effectively bypasses the compile-time exception - * checking that would otherwise be performed by the compiler. - * The {@link - * java.lang.reflect.Constructor#newInstance(java.lang.Object...) - * Constructor.newInstance} method avoids this problem by wrapping - * any exception thrown by the constructor in a (checked) {@link - * java.lang.reflect.InvocationTargetException}. - * - * @return a newly allocated instance of the class represented by this - * object. - * @throws IllegalAccessException if the class or its nullary - * constructor is not accessible. - * @throws InstantiationException - * if this {@code Class} represents an abstract class, - * an interface, an array class, a primitive type, or void; - * or if the class has no nullary constructor; - * or if the instantiation fails for some other reason. - * @throws ExceptionInInitializerError if the initialization - * provoked by this method fails. - * @throws SecurityException - * If a security manager, <i>s</i>, is present and - * the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class. - */ - @CallerSensitive - public T newInstance() - throws InstantiationException, IllegalAccessException - { - if (System.getSecurityManager() != null) { - checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false); - } - - // NOTE: the following code may not be strictly correct under - // the current Java memory model. - - // Constructor lookup - if (cachedConstructor == null) { - if (this == Class.class) { - throw new IllegalAccessException( - "Can not call newInstance() on the Class for java.lang.Class" - ); - } - try { - Class<?>[] empty = {}; - final Constructor<T> c = getConstructor0(empty, Member.DECLARED); - // Disable accessibility checks on the constructor - // since we have to do the security check here anyway - // (the stack depth is wrong for the Constructor's - // security check to work) - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Void>() { - public Void run() { - c.setAccessible(true); - return null; - } - }); - cachedConstructor = c; - } catch (NoSuchMethodException e) { - throw (InstantiationException) - new InstantiationException(getName()).initCause(e); - } - } - Constructor<T> tmpConstructor = cachedConstructor; - // Security check (same as in java.lang.reflect.Constructor) - int modifiers = tmpConstructor.getModifiers(); - if (!Reflection.quickCheckMemberAccess(this, modifiers)) { - Class<?> caller = Reflection.getCallerClass(); - if (newInstanceCallerCache != caller) { - Reflection.ensureMemberAccess(caller, this, null, modifiers); - newInstanceCallerCache = caller; - } - } - // Run constructor - try { - return tmpConstructor.newInstance((Object[])null); - } catch (InvocationTargetException e) { - Unsafe.getUnsafe().throwException(e.getTargetException()); - // Not reached - return null; - } - } - private volatile transient Constructor<T> cachedConstructor; - private volatile transient Class<?> newInstanceCallerCache; - - - /** - * Determines if the specified {@code Object} is assignment-compatible - * with the object represented by this {@code Class}. This method is - * the dynamic equivalent of the Java language {@code instanceof} - * operator. The method returns {@code true} if the specified - * {@code Object} argument is non-null and can be cast to the - * reference type represented by this {@code Class} object without - * raising a {@code ClassCastException.} It returns {@code false} - * otherwise. - * - * <p> Specifically, if this {@code Class} object represents a - * declared class, this method returns {@code true} if the specified - * {@code Object} argument is an instance of the represented class (or - * of any of its subclasses); it returns {@code false} otherwise. If - * this {@code Class} object represents an array class, this method - * returns {@code true} if the specified {@code Object} argument - * can be converted to an object of the array class by an identity - * conversion or by a widening reference conversion; it returns - * {@code false} otherwise. If this {@code Class} object - * represents an interface, this method returns {@code true} if the - * class or any superclass of the specified {@code Object} argument - * implements this interface; it returns {@code false} otherwise. If - * this {@code Class} object represents a primitive type, this method - * returns {@code false}. - * - * @param obj the object to check - * @return true if {@code obj} is an instance of this class - * - * @since JDK1.1 - */ - public native boolean isInstance(Object obj); - - - /** - * Determines if the class or interface represented by this - * {@code Class} object is either the same as, or is a superclass or - * superinterface of, the class or interface represented by the specified - * {@code Class} parameter. It returns {@code true} if so; - * otherwise it returns {@code false}. If this {@code Class} - * object represents a primitive type, this method returns - * {@code true} if the specified {@code Class} parameter is - * exactly this {@code Class} object; otherwise it returns - * {@code false}. - * - * <p> Specifically, this method tests whether the type represented by the - * specified {@code Class} parameter can be converted to the type - * represented by this {@code Class} object via an identity conversion - * or via a widening reference conversion. See <em>The Java Language - * Specification</em>, sections 5.1.1 and 5.1.4 , for details. - * - * @param cls the {@code Class} object to be checked - * @return the {@code boolean} value indicating whether objects of the - * type {@code cls} can be assigned to objects of this class - * @exception NullPointerException if the specified Class parameter is - * null. - * @since JDK1.1 - */ - public native boolean isAssignableFrom(Class<?> cls); - - - /** - * Determines if the specified {@code Class} object represents an - * interface type. - * - * @return {@code true} if this object represents an interface; - * {@code false} otherwise. - */ - public native boolean isInterface(); - - - /** - * Determines if this {@code Class} object represents an array class. - * - * @return {@code true} if this object represents an array class; - * {@code false} otherwise. - * @since JDK1.1 - */ - public native boolean isArray(); - - - /** - * Determines if the specified {@code Class} object represents a - * primitive type. - * - * <p> There are nine predefined {@code Class} objects to represent - * the eight primitive types and void. These are created by the Java - * Virtual Machine, and have the same names as the primitive types that - * they represent, namely {@code boolean}, {@code byte}, - * {@code char}, {@code short}, {@code int}, - * {@code long}, {@code float}, and {@code double}. - * - * <p> These objects may only be accessed via the following public static - * final variables, and are the only {@code Class} objects for which - * this method returns {@code true}. - * - * @return true if and only if this class represents a primitive type - * - * @see java.lang.Boolean#TYPE - * @see java.lang.Character#TYPE - * @see java.lang.Byte#TYPE - * @see java.lang.Short#TYPE - * @see java.lang.Integer#TYPE - * @see java.lang.Long#TYPE - * @see java.lang.Float#TYPE - * @see java.lang.Double#TYPE - * @see java.lang.Void#TYPE - * @since JDK1.1 - */ - public native boolean isPrimitive(); - - /** - * Returns true if this {@code Class} object represents an annotation - * type. Note that if this method returns true, {@link #isInterface()} - * would also return true, as all annotation types are also interfaces. - * - * @return {@code true} if this class object represents an annotation - * type; {@code false} otherwise - * @since 1.5 - */ - public boolean isAnnotation() { - return (getModifiers() & ANNOTATION) != 0; - } - - /** - * Returns {@code true} if this class is a synthetic class; - * returns {@code false} otherwise. - * @return {@code true} if and only if this class is a synthetic class as - * defined by the Java Language Specification. - * @jls 13.1 The Form of a Binary - * @since 1.5 - */ - public boolean isSynthetic() { - return (getModifiers() & SYNTHETIC) != 0; - } - - /** - * Returns the name of the entity (class, interface, array class, - * primitive type, or void) represented by this {@code Class} object, - * as a {@code String}. - * - * <p> If this class object represents a reference type that is not an - * array type then the binary name of the class is returned, as specified - * by - * <cite>The Java™ Language Specification</cite>. - * - * <p> If this class object represents a primitive type or void, then the - * name returned is a {@code String} equal to the Java language - * keyword corresponding to the primitive type or void. - * - * <p> If this class object represents a class of arrays, then the internal - * form of the name consists of the name of the element type preceded by - * one or more '{@code [}' characters representing the depth of the array - * nesting. The encoding of element type names is as follows: - * - * <blockquote><table summary="Element types and encodings"> - * <tr><th> Element Type <th> <th> Encoding - * <tr><td> boolean <td> <td align=center> Z - * <tr><td> byte <td> <td align=center> B - * <tr><td> char <td> <td align=center> C - * <tr><td> class or interface - * <td> <td align=center> L<i>classname</i>; - * <tr><td> double <td> <td align=center> D - * <tr><td> float <td> <td align=center> F - * <tr><td> int <td> <td align=center> I - * <tr><td> long <td> <td align=center> J - * <tr><td> short <td> <td align=center> S - * </table></blockquote> - * - * <p> The class or interface name <i>classname</i> is the binary name of - * the class specified above. - * - * <p> Examples: - * <blockquote><pre> - * String.class.getName() - * returns "java.lang.String" - * byte.class.getName() - * returns "byte" - * (new Object[3]).getClass().getName() - * returns "[Ljava.lang.Object;" - * (new int[3][4][5][6][7][8][9]).getClass().getName() - * returns "[[[[[[[I" - * </pre></blockquote> - * - * @return the name of the class or interface - * represented by this object. - */ - public String getName() { - String name = this.name; - if (name == null) - this.name = name = getName0(); - return name; - } - - // cache the name to reduce the number of calls into the VM - private transient String name; - private native String getName0(); - - /** - * Returns the class loader for the class. Some implementations may use - * null to represent the bootstrap class loader. This method will return - * null in such implementations if this class was loaded by the bootstrap - * class loader. - * - * <p> If a security manager is present, and the caller's class loader is - * not null and the caller's class loader is not the same as or an ancestor of - * the class loader for the class whose class loader is requested, then - * this method calls the security manager's {@code checkPermission} - * method with a {@code RuntimePermission("getClassLoader")} - * permission to ensure it's ok to access the class loader for the class. - * - * <p>If this object - * represents a primitive type or void, null is returned. - * - * @return the class loader that loaded the class or interface - * represented by this object. - * @throws SecurityException - * if a security manager exists and its - * {@code checkPermission} method denies - * access to the class loader for the class. - * @see java.lang.ClassLoader - * @see SecurityManager#checkPermission - * @see java.lang.RuntimePermission - */ - @CallerSensitive - public ClassLoader getClassLoader() { - ClassLoader cl = getClassLoader0(); - if (cl == null) - return null; - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass()); - } - return cl; - } - - // Package-private to allow ClassLoader access - native ClassLoader getClassLoader0(); - - - /** - * 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 java.lang.reflect.GenericSignatureFormatError if the generic - * signature of this generic declaration does not conform to - * the format specified in - * <cite>The Java™ Virtual Machine Specification</cite> - * @since 1.5 - */ - @SuppressWarnings("unchecked") - public TypeVariable<Class<T>>[] getTypeParameters() { - ClassRepository info = getGenericInfo(); - if (info != null) - return (TypeVariable<Class<T>>[])info.getTypeParameters(); - else - return (TypeVariable<Class<T>>[])new TypeVariable<?>[0]; - } - - - /** - * Returns the {@code Class} representing the superclass of the entity - * (class, interface, primitive type or void) represented by this - * {@code Class}. If this {@code Class} represents either the - * {@code Object} class, an interface, a primitive type, or void, then - * null is returned. If this object represents an array class then the - * {@code Class} object representing the {@code Object} class is - * returned. - * - * @return the superclass of the class represented by this object. - */ - public native Class<? super T> getSuperclass(); - - - /** - * Returns the {@code Type} representing the direct superclass of - * the entity (class, interface, primitive type or void) represented by - * this {@code Class}. - * - * <p>If the superclass is a parameterized type, the {@code Type} - * object returned must accurately reflect the actual type - * parameters used in the source code. The parameterized type - * representing the superclass is created if it had not been - * created before. See the declaration of {@link - * java.lang.reflect.ParameterizedType ParameterizedType} for the - * semantics of the creation process for parameterized types. If - * this {@code Class} represents either the {@code Object} - * class, an interface, a primitive type, or void, then null is - * returned. If this object represents an array class then the - * {@code Class} object representing the {@code Object} class is - * returned. - * - * @throws java.lang.reflect.GenericSignatureFormatError if the generic - * class signature does not conform to the format specified in - * <cite>The Java™ Virtual Machine Specification</cite> - * @throws TypeNotPresentException if the generic superclass - * refers to a non-existent type declaration - * @throws java.lang.reflect.MalformedParameterizedTypeException if the - * generic superclass refers to a parameterized type that cannot be - * instantiated for any reason - * @return the superclass of the class represented by this object - * @since 1.5 - */ - public Type getGenericSuperclass() { - ClassRepository info = getGenericInfo(); - if (info == null) { - return getSuperclass(); - } - - // Historical irregularity: - // Generic signature marks interfaces with superclass = Object - // but this API returns null for interfaces - if (isInterface()) { - return null; - } - - return info.getSuperclass(); - } - - /** - * Gets the package for this class. The class loader of this class is used - * to find the package. If the class was loaded by the bootstrap class - * loader the set of packages loaded from CLASSPATH is searched to find the - * package of the class. Null is returned if no package object was created - * by the class loader of this class. - * - * <p> Packages have attributes for versions and specifications only if the - * information was defined in the manifests that accompany the classes, and - * if the class loader created the package instance with the attributes - * from the manifest. - * - * @return the package of the class, or null if no package - * information is available from the archive or codebase. - */ - public Package getPackage() { - return Package.getPackage(this); - } - - - /** - * Determines the interfaces implemented by the class or interface - * represented by this object. - * - * <p> If this object represents a class, the return value is an array - * containing objects representing all interfaces implemented by the - * class. The order of the interface objects in the array corresponds to - * the order of the interface names in the {@code implements} clause - * of the declaration of the class represented by this object. For - * example, given the declaration: - * <blockquote> - * {@code class Shimmer implements FloorWax, DessertTopping { ... }} - * </blockquote> - * suppose the value of {@code s} is an instance of - * {@code Shimmer}; the value of the expression: - * <blockquote> - * {@code s.getClass().getInterfaces()[0]} - * </blockquote> - * is the {@code Class} object that represents interface - * {@code FloorWax}; and the value of: - * <blockquote> - * {@code s.getClass().getInterfaces()[1]} - * </blockquote> - * is the {@code Class} object that represents interface - * {@code DessertTopping}. - * - * <p> If this object represents an interface, the array contains objects - * representing all interfaces extended by the interface. The order of the - * interface objects in the array corresponds to the order of the interface - * names in the {@code extends} clause of the declaration of the - * interface represented by this object. - * - * <p> If this object represents a class or interface that implements no - * interfaces, the method returns an array of length 0. - * - * <p> If this object represents a primitive type or void, the method - * returns an array of length 0. - * - * <p> If this {@code Class} object represents an array type, the - * interfaces {@code Cloneable} and {@code java.io.Serializable} are - * returned in that order. - * - * @return an array of interfaces implemented by this class. - */ - public Class<?>[] getInterfaces() { - ReflectionData<T> rd = reflectionData(); - if (rd == null) { - // no cloning required - return getInterfaces0(); - } else { - Class<?>[] interfaces = rd.interfaces; - if (interfaces == null) { - interfaces = getInterfaces0(); - rd.interfaces = interfaces; - } - // defensively copy before handing over to user code - return interfaces.clone(); - } - } - - private native Class<?>[] getInterfaces0(); - - /** - * Returns the {@code Type}s representing the interfaces - * directly implemented by the class or interface represented by - * this object. - * - * <p>If a superinterface is a parameterized type, the - * {@code Type} object returned for it must accurately reflect - * the actual type parameters used in the source code. The - * parameterized type representing each superinterface is created - * if it had not been created before. See the declaration of - * {@link java.lang.reflect.ParameterizedType ParameterizedType} - * for the semantics of the creation process for parameterized - * types. - * - * <p> If this object represents a class, the return value is an - * array containing objects representing all interfaces - * implemented by the class. The order of the interface objects in - * the array corresponds to the order of the interface names in - * the {@code implements} clause of the declaration of the class - * represented by this object. In the case of an array class, the - * interfaces {@code Cloneable} and {@code Serializable} are - * returned in that order. - * - * <p>If this object represents an interface, the array contains - * objects representing all interfaces directly extended by the - * interface. The order of the interface objects in the array - * corresponds to the order of the interface names in the - * {@code extends} clause of the declaration of the interface - * represented by this object. - * - * <p>If this object represents a class or interface that - * implements no interfaces, the method returns an array of length - * 0. - * - * <p>If this object represents a primitive type or void, the - * method returns an array of length 0. - * - * @throws java.lang.reflect.GenericSignatureFormatError - * if the generic class signature does not conform to the format - * specified in - * <cite>The Java™ Virtual Machine Specification</cite> - * @throws TypeNotPresentException if any of the generic - * superinterfaces refers to a non-existent type declaration - * @throws java.lang.reflect.MalformedParameterizedTypeException - * if any of the generic superinterfaces refer to a parameterized - * type that cannot be instantiated for any reason - * @return an array of interfaces implemented by this class - * @since 1.5 - */ - public Type[] getGenericInterfaces() { - ClassRepository info = getGenericInfo(); - return (info == null) ? getInterfaces() : info.getSuperInterfaces(); - } - - - /** - * Returns the {@code Class} representing the component type of an - * array. If this class does not represent an array class this method - * returns null. - * - * @return the {@code Class} representing the component type of this - * class if this class is an array - * @see java.lang.reflect.Array - * @since JDK1.1 - */ - public native Class<?> getComponentType(); - - - /** - * Returns the Java language modifiers for this class or interface, encoded - * in an integer. The modifiers consist of the Java Virtual Machine's - * constants for {@code public}, {@code protected}, - * {@code private}, {@code final}, {@code static}, - * {@code abstract} and {@code interface}; they should be decoded - * using the methods of class {@code Modifier}. - * - * <p> If the underlying class is an array class, then its - * {@code public}, {@code private} and {@code protected} - * modifiers are the same as those of its component type. If this - * {@code Class} represents a primitive type or void, its - * {@code public} modifier is always {@code true}, and its - * {@code protected} and {@code private} modifiers are always - * {@code false}. If this object represents an array class, a - * primitive type or void, then its {@code final} modifier is always - * {@code true} and its interface modifier is always - * {@code false}. The values of its other modifiers are not determined - * by this specification. - * - * <p> The modifier encodings are defined in <em>The Java Virtual Machine - * Specification</em>, table 4.1. - * - * @return the {@code int} representing the modifiers for this class - * @see java.lang.reflect.Modifier - * @since JDK1.1 - */ - public native int getModifiers(); - - - /** - * Gets the signers of this class. - * - * @return the signers of this class, or null if there are no signers. In - * particular, this method returns null if this object represents - * a primitive type or void. - * @since JDK1.1 - */ - public native Object[] getSigners(); - - - /** - * Set the signers of this class. - */ - native void setSigners(Object[] signers); - - - /** - * If this {@code Class} object represents a local or anonymous - * class within a method, returns a {@link - * java.lang.reflect.Method Method} object representing the - * immediately enclosing method of the underlying class. Returns - * {@code null} otherwise. - * - * In particular, this method returns {@code null} if the underlying - * class is a local or anonymous class immediately enclosed by a type - * declaration, instance initializer or static initializer. - * - * @return the immediately enclosing method of the underlying class, if - * that class is a local or anonymous class; otherwise {@code null}. - * - * @throws SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: - * - * <ul> - * - * <li> the caller's class loader is not the same as the - * class loader of the enclosing class and invocation of - * {@link SecurityManager#checkPermission - * s.checkPermission} method with - * {@code RuntimePermission("accessDeclaredMembers")} - * denies access to the methods within the enclosing class - * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the enclosing class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of the enclosing class - * - * </ul> - * @since 1.5 - */ - @CallerSensitive - public Method getEnclosingMethod() throws SecurityException { - EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo(); - - if (enclosingInfo == null) - return null; - else { - if (!enclosingInfo.isMethod()) - return null; - - MethodRepository typeInfo = MethodRepository.make(enclosingInfo.getDescriptor(), - getFactory()); - Class<?> returnType = toClass(typeInfo.getReturnType()); - Type [] parameterTypes = typeInfo.getParameterTypes(); - Class<?>[] parameterClasses = new Class<?>[parameterTypes.length]; - - // Convert Types to Classes; returned types *should* - // be class objects since the methodDescriptor's used - // don't have generics information - for(int i = 0; i < parameterClasses.length; i++) - parameterClasses[i] = toClass(parameterTypes[i]); - - // Perform access check - Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass(); - enclosingCandidate.checkMemberAccess(Member.DECLARED, - Reflection.getCallerClass(), true); - /* - * Loop over all declared methods; match method name, - * number of and type of parameters, *and* return - * type. Matching return type is also necessary - * because of covariant returns, etc. - */ - for(Method m: enclosingCandidate.getDeclaredMethods()) { - if (m.getName().equals(enclosingInfo.getName()) ) { - Class<?>[] candidateParamClasses = m.getParameterTypes(); - if (candidateParamClasses.length == parameterClasses.length) { - boolean matches = true; - for(int i = 0; i < candidateParamClasses.length; i++) { - if (!candidateParamClasses[i].equals(parameterClasses[i])) { - matches = false; - break; - } - } - - if (matches) { // finally, check return type - if (m.getReturnType().equals(returnType) ) - return m; - } - } - } - } - - throw new InternalError("Enclosing method not found"); - } - } - - private native Object[] getEnclosingMethod0(); - - private EnclosingMethodInfo getEnclosingMethodInfo() { - Object[] enclosingInfo = getEnclosingMethod0(); - if (enclosingInfo == null) - return null; - else { - return new EnclosingMethodInfo(enclosingInfo); - } - } - - private final static class EnclosingMethodInfo { - private Class<?> enclosingClass; - private String name; - private String descriptor; - - private EnclosingMethodInfo(Object[] enclosingInfo) { - if (enclosingInfo.length != 3) - throw new InternalError("Malformed enclosing method information"); - try { - // The array is expected to have three elements: - - // the immediately enclosing class - enclosingClass = (Class<?>) enclosingInfo[0]; - assert(enclosingClass != null); - - // the immediately enclosing method or constructor's - // name (can be null). - name = (String) enclosingInfo[1]; - - // the immediately enclosing method or constructor's - // descriptor (null iff name is). - descriptor = (String) enclosingInfo[2]; - assert((name != null && descriptor != null) || name == descriptor); - } catch (ClassCastException cce) { - throw new InternalError("Invalid type in enclosing method information", cce); - } - } - - boolean isPartial() { - return enclosingClass == null || name == null || descriptor == null; - } - - boolean isConstructor() { return !isPartial() && "<init>".equals(name); } - - boolean isMethod() { return !isPartial() && !isConstructor() && !"<clinit>".equals(name); } - - Class<?> getEnclosingClass() { return enclosingClass; } - - String getName() { return name; } - - String getDescriptor() { return descriptor; } - - } - - private static Class<?> toClass(Type o) { - if (o instanceof GenericArrayType) - return Array.newInstance(toClass(((GenericArrayType)o).getGenericComponentType()), - 0) - .getClass(); - return (Class<?>)o; - } - - /** - * If this {@code Class} object represents a local or anonymous - * class within a constructor, returns a {@link - * java.lang.reflect.Constructor Constructor} object representing - * the immediately enclosing constructor of the underlying - * class. Returns {@code null} otherwise. In particular, this - * method returns {@code null} if the underlying class is a local - * or anonymous class immediately enclosed by a type declaration, - * instance initializer or static initializer. - * - * @return the immediately enclosing constructor of the underlying class, if - * that class is a local or anonymous class; otherwise {@code null}. - * @throws SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: - * - * <ul> - * - * <li> the caller's class loader is not the same as the - * class loader of the enclosing class and invocation of - * {@link SecurityManager#checkPermission - * s.checkPermission} method with - * {@code RuntimePermission("accessDeclaredMembers")} - * denies access to the constructors within the enclosing class - * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the enclosing class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of the enclosing class - * - * </ul> - * @since 1.5 - */ - @CallerSensitive - public Constructor<?> getEnclosingConstructor() throws SecurityException { - EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo(); - - if (enclosingInfo == null) - return null; - else { - if (!enclosingInfo.isConstructor()) - return null; - - ConstructorRepository typeInfo = ConstructorRepository.make(enclosingInfo.getDescriptor(), - getFactory()); - Type [] parameterTypes = typeInfo.getParameterTypes(); - Class<?>[] parameterClasses = new Class<?>[parameterTypes.length]; - - // Convert Types to Classes; returned types *should* - // be class objects since the methodDescriptor's used - // don't have generics information - for(int i = 0; i < parameterClasses.length; i++) - parameterClasses[i] = toClass(parameterTypes[i]); - - // Perform access check - Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass(); - enclosingCandidate.checkMemberAccess(Member.DECLARED, - Reflection.getCallerClass(), true); - /* - * Loop over all declared constructors; match number - * of and type of parameters. - */ - for(Constructor<?> c: enclosingCandidate.getDeclaredConstructors()) { - Class<?>[] candidateParamClasses = c.getParameterTypes(); - if (candidateParamClasses.length == parameterClasses.length) { - boolean matches = true; - for(int i = 0; i < candidateParamClasses.length; i++) { - if (!candidateParamClasses[i].equals(parameterClasses[i])) { - matches = false; - break; - } - } - - if (matches) - return c; - } - } - - throw new InternalError("Enclosing constructor not found"); - } - } - - - /** - * If the class or interface represented by this {@code Class} object - * is a member of another class, returns the {@code Class} object - * representing the class in which it was declared. This method returns - * null if this class or interface is not a member of any other class. If - * this {@code Class} object represents an array class, a primitive - * type, or void,then this method returns null. - * - * @return the declaring class for this class - * @throws SecurityException - * If a security manager, <i>s</i>, is present and the caller's - * class loader is not the same as or an ancestor of the class - * loader for the declaring class and invocation of {@link - * SecurityManager#checkPackageAccess s.checkPackageAccess()} - * denies access to the package of the declaring class - * @since JDK1.1 - */ - @CallerSensitive - public Class<?> getDeclaringClass() throws SecurityException { - final Class<?> candidate = getDeclaringClass0(); - - if (candidate != null) - candidate.checkPackageAccess( - ClassLoader.getClassLoader(Reflection.getCallerClass()), true); - return candidate; - } - - private native Class<?> getDeclaringClass0(); - - - /** - * Returns the immediately enclosing class of the underlying - * class. If the underlying class is a top level class this - * method returns {@code null}. - * @return the immediately enclosing class of the underlying class - * @exception SecurityException - * If a security manager, <i>s</i>, is present and the caller's - * class loader is not the same as or an ancestor of the class - * loader for the enclosing class and invocation of {@link - * SecurityManager#checkPackageAccess s.checkPackageAccess()} - * denies access to the package of the enclosing class - * @since 1.5 - */ - @CallerSensitive - public Class<?> getEnclosingClass() throws SecurityException { - // There are five kinds of classes (or interfaces): - // a) Top level classes - // b) Nested classes (static member classes) - // c) Inner classes (non-static member classes) - // d) Local classes (named classes declared within a method) - // e) Anonymous classes - - - // JVM Spec 4.8.6: A class must have an EnclosingMethod - // attribute if and only if it is a local class or an - // anonymous class. - EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo(); - Class<?> enclosingCandidate; - - if (enclosingInfo == null) { - // This is a top level or a nested class or an inner class (a, b, or c) - enclosingCandidate = getDeclaringClass(); - } else { - Class<?> enclosingClass = enclosingInfo.getEnclosingClass(); - // This is a local class or an anonymous class (d or e) - if (enclosingClass == this || enclosingClass == null) - throw new InternalError("Malformed enclosing method information"); - else - enclosingCandidate = enclosingClass; - } - - if (enclosingCandidate != null) - enclosingCandidate.checkPackageAccess( - ClassLoader.getClassLoader(Reflection.getCallerClass()), true); - return enclosingCandidate; - } - - /** - * Returns the simple name of the underlying class as given in the - * source code. Returns an empty string if the underlying class is - * anonymous. - * - * <p>The simple name of an array is the simple name of the - * component type with "[]" appended. In particular the simple - * name of an array whose component type is anonymous is "[]". - * - * @return the simple name of the underlying class - * @since 1.5 - */ - public String getSimpleName() { - if (isArray()) - return getComponentType().getSimpleName()+"[]"; - - String simpleName = getSimpleBinaryName(); - if (simpleName == null) { // top level class - simpleName = getName(); - return simpleName.substring(simpleName.lastIndexOf(".")+1); // strip the package name - } - // According to JLS3 "Binary Compatibility" (13.1) the binary - // name of non-package classes (not top level) is the binary - // name of the immediately enclosing class followed by a '$' followed by: - // (for nested and inner classes): the simple name. - // (for local classes): 1 or more digits followed by the simple name. - // (for anonymous classes): 1 or more digits. - - // Since getSimpleBinaryName() will strip the binary name of - // the immediatly enclosing class, we are now looking at a - // string that matches the regular expression "\$[0-9]*" - // followed by a simple name (considering the simple of an - // anonymous class to be the empty string). - - // Remove leading "\$[0-9]*" from the name - int length = simpleName.length(); - if (length < 1 || simpleName.charAt(0) != '$') - throw new InternalError("Malformed class name"); - int index = 1; - while (index < length && isAsciiDigit(simpleName.charAt(index))) - index++; - // Eventually, this is the empty string iff this is an anonymous class - return simpleName.substring(index); - } - - /** - * Return an informative string for the name of this type. - * - * @return an informative string for the name of this type - * @since 1.8 - */ - public String getTypeName() { - if (isArray()) { - try { - Class<?> cl = this; - int dimensions = 0; - while (cl.isArray()) { - dimensions++; - cl = cl.getComponentType(); - } - StringBuilder sb = new StringBuilder(); - sb.append(cl.getName()); - for (int i = 0; i < dimensions; i++) { - sb.append("[]"); - } - return sb.toString(); - } catch (Throwable e) { /*FALLTHRU*/ } - } - return getName(); - } - - /** - * Character.isDigit answers {@code true} to some non-ascii - * digits. This one does not. - */ - private static boolean isAsciiDigit(char c) { - return '0' <= c && c <= '9'; - } - - /** - * Returns the canonical name of the underlying class as - * defined by the Java Language Specification. Returns null if - * the underlying class does not have a canonical name (i.e., if - * it is a local or anonymous class or an array whose component - * type does not have a canonical name). - * @return the canonical name of the underlying class if it exists, and - * {@code null} otherwise. - * @since 1.5 - */ - public String getCanonicalName() { - if (isArray()) { - String canonicalName = getComponentType().getCanonicalName(); - if (canonicalName != null) - return canonicalName + "[]"; - else - return null; - } - if (isLocalOrAnonymousClass()) - return null; - Class<?> enclosingClass = getEnclosingClass(); - if (enclosingClass == null) { // top level class - return getName(); - } else { - String enclosingName = enclosingClass.getCanonicalName(); - if (enclosingName == null) - return null; - return enclosingName + "." + getSimpleName(); - } - } - - /** - * Returns {@code true} if and only if the underlying class - * is an anonymous class. - * - * @return {@code true} if and only if this class is an anonymous class. - * @since 1.5 - */ - public boolean isAnonymousClass() { - return "".equals(getSimpleName()); - } - - /** - * Returns {@code true} if and only if the underlying class - * is a local class. - * - * @return {@code true} if and only if this class is a local class. - * @since 1.5 - */ - public boolean isLocalClass() { - return isLocalOrAnonymousClass() && !isAnonymousClass(); - } - - /** - * Returns {@code true} if and only if the underlying class - * is a member class. - * - * @return {@code true} if and only if this class is a member class. - * @since 1.5 - */ - public boolean isMemberClass() { - return getSimpleBinaryName() != null && !isLocalOrAnonymousClass(); - } - - /** - * Returns the "simple binary name" of the underlying class, i.e., - * the binary name without the leading enclosing class name. - * Returns {@code null} if the underlying class is a top level - * class. - */ - private String getSimpleBinaryName() { - Class<?> enclosingClass = getEnclosingClass(); - if (enclosingClass == null) // top level class - return null; - // Otherwise, strip the enclosing class' name - try { - return getName().substring(enclosingClass.getName().length()); - } catch (IndexOutOfBoundsException ex) { - throw new InternalError("Malformed class name", ex); - } - } - - /** - * Returns {@code true} if this is a local class or an anonymous - * class. Returns {@code false} otherwise. - */ - private boolean isLocalOrAnonymousClass() { - // JVM Spec 4.8.6: A class must have an EnclosingMethod - // attribute if and only if it is a local class or an - // anonymous class. - return getEnclosingMethodInfo() != null; - } - - /** - * Returns an array containing {@code Class} objects representing all - * the public classes and interfaces that are members of the class - * represented by this {@code Class} object. This includes public - * class and interface members inherited from superclasses and public class - * and interface members declared by the class. This method returns an - * array of length 0 if this {@code Class} object has no public member - * classes or interfaces. This method also returns an array of length 0 if - * this {@code Class} object represents a primitive type, an array - * class, or void. - * - * @return the array of {@code Class} objects representing the public - * members of this class - * @throws SecurityException - * If a security manager, <i>s</i>, is present and - * the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class. - * - * @since JDK1.1 - */ - @CallerSensitive - public Class<?>[] getClasses() { - checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false); - - // Privileged so this implementation can look at DECLARED classes, - // something the caller might not have privilege to do. The code here - // is allowed to look at DECLARED classes because (1) it does not hand - // out anything other than public members and (2) public member access - // has already been ok'd by the SecurityManager. - - return java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Class<?>[]>() { - public Class<?>[] run() { - List<Class<?>> list = new ArrayList<>(); - Class<?> currentClass = Class.this; - while (currentClass != null) { - Class<?>[] members = currentClass.getDeclaredClasses(); - for (int i = 0; i < members.length; i++) { - if (Modifier.isPublic(members[i].getModifiers())) { - list.add(members[i]); - } - } - currentClass = currentClass.getSuperclass(); - } - return list.toArray(new Class<?>[0]); - } - }); - } - - - /** - * Returns an array containing {@code Field} objects reflecting all - * the accessible public fields of the class or interface represented by - * this {@code Class} object. - * - * <p> If this {@code Class} object represents a class or interface with no - * no accessible public fields, then this method returns an array of length - * 0. - * - * <p> If this {@code Class} object represents a class, then this method - * returns the public fields of the class and of all its superclasses. - * - * <p> If this {@code Class} object represents an interface, then this - * method returns the fields of the interface and of all its - * superinterfaces. - * - * <p> If this {@code Class} object represents an array type, a primitive - * type, or void, then this method returns an array of length 0. - * - * <p> The elements in the returned array are not sorted and are not in any - * particular order. - * - * @return the array of {@code Field} objects representing the - * public fields - * @throws SecurityException - * If a security manager, <i>s</i>, is present and - * the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class. - * - * @since JDK1.1 - * @jls 8.2 Class Members - * @jls 8.3 Field Declarations - */ - @CallerSensitive - public Field[] getFields() throws SecurityException { - checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); - return copyFields(privateGetPublicFields(null)); - } - - - /** - * Returns an array containing {@code Method} objects reflecting all the - * public methods of the class or interface represented by this {@code - * Class} object, including those declared by the class or interface and - * those inherited from superclasses and superinterfaces. - * - * <p> If this {@code Class} object represents a type that has multiple - * public methods with the same name and parameter types, but different - * return types, then the returned array has a {@code Method} object for - * each such method. - * - * <p> If this {@code Class} object represents a type with a class - * initialization method {@code <clinit>}, then the returned array does - * <em>not</em> have a corresponding {@code Method} object. - * - * <p> If this {@code Class} object represents an array type, then the - * returned array has a {@code Method} object for each of the public - * methods inherited by the array type from {@code Object}. It does not - * contain a {@code Method} object for {@code clone()}. - * - * <p> If this {@code Class} object represents an interface then the - * returned array does not contain any implicitly declared methods from - * {@code Object}. Therefore, if no methods are explicitly declared in - * this interface or any of its superinterfaces then the returned array - * has length 0. (Note that a {@code Class} object which represents a class - * always has public methods, inherited from {@code Object}.) - * - * <p> If this {@code Class} object represents a primitive type or void, - * then the returned array has length 0. - * - * <p> Static methods declared in superinterfaces of the class or interface - * represented by this {@code Class} object are not considered members of - * the class or interface. - * - * <p> The elements in the returned array are not sorted and are not in any - * particular order. - * - * @return the array of {@code Method} objects representing the - * public methods of this class - * @throws SecurityException - * If a security manager, <i>s</i>, is present and - * the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class. - * - * @jls 8.2 Class Members - * @jls 8.4 Method Declarations - * @since JDK1.1 - */ - @CallerSensitive - public Method[] getMethods() throws SecurityException { - checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); - return copyMethods(privateGetPublicMethods()); - } - - - /** - * Returns an array containing {@code Constructor} objects reflecting - * all the public constructors of the class represented by this - * {@code Class} object. An array of length 0 is returned if the - * class has no public constructors, or if the class is an array class, or - * if the class reflects a primitive type or void. - * - * Note that while this method returns an array of {@code - * Constructor<T>} objects (that is an array of constructors from - * this class), the return type of this method is {@code - * Constructor<?>[]} and <em>not</em> {@code Constructor<T>[]} as - * might be expected. This less informative return type is - * necessary since after being returned from this method, the - * array could be modified to hold {@code Constructor} objects for - * different classes, which would violate the type guarantees of - * {@code Constructor<T>[]}. - * - * @return the array of {@code Constructor} objects representing the - * public constructors of this class - * @throws SecurityException - * If a security manager, <i>s</i>, is present and - * the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class. - * - * @since JDK1.1 - */ - @CallerSensitive - public Constructor<?>[] getConstructors() throws SecurityException { - checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); - return copyConstructors(privateGetDeclaredConstructors(true)); - } - - - /** - * Returns a {@code Field} object that reflects the specified public member - * field of the class or interface represented by this {@code Class} - * object. The {@code name} parameter is a {@code String} specifying the - * simple name of the desired field. - * - * <p> The field to be reflected is determined by the algorithm that - * follows. Let C be the class or interface represented by this object: - * - * <OL> - * <LI> If C declares a public field with the name specified, that is the - * field to be reflected.</LI> - * <LI> If no field was found in step 1 above, this algorithm is applied - * recursively to each direct superinterface of C. The direct - * superinterfaces are searched in the order they were declared.</LI> - * <LI> If no field was found in steps 1 and 2 above, and C has a - * superclass S, then this algorithm is invoked recursively upon S. - * If C has no superclass, then a {@code NoSuchFieldException} - * is thrown.</LI> - * </OL> - * - * <p> If this {@code Class} object represents an array type, then this - * method does not find the {@code length} field of the array type. - * - * @param name the field name - * @return the {@code Field} object of this class specified by - * {@code name} - * @throws NoSuchFieldException if a field with the specified name is - * not found. - * @throws NullPointerException if {@code name} is {@code null} - * @throws SecurityException - * If a security manager, <i>s</i>, is present and - * the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class. - * - * @since JDK1.1 - * @jls 8.2 Class Members - * @jls 8.3 Field Declarations - */ - @CallerSensitive - public Field getField(String name) - throws NoSuchFieldException, SecurityException { - checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); - Field field = getField0(name); - if (field == null) { - throw new NoSuchFieldException(name); - } - return field; - } - - - /** - * Returns a {@code Method} object that reflects the specified public - * member method of the class or interface represented by this - * {@code Class} object. The {@code name} parameter is a - * {@code String} specifying the simple name of the desired method. The - * {@code parameterTypes} parameter is an array of {@code Class} - * objects that identify the method's formal parameter types, in declared - * order. If {@code parameterTypes} is {@code null}, it is - * treated as if it were an empty array. - * - * <p> If the {@code name} is "{@code <init>}" or "{@code <clinit>}" a - * {@code NoSuchMethodException} is raised. Otherwise, the method to - * be reflected is determined by the algorithm that follows. Let C be the - * class or interface represented by this object: - * <OL> - * <LI> C is searched for a <I>matching method</I>, as defined below. If a - * matching method is found, it is reflected.</LI> - * <LI> If no matching method is found by step 1 then: - * <OL TYPE="a"> - * <LI> If C is a class other than {@code Object}, then this algorithm is - * invoked recursively on the superclass of C.</LI> - * <LI> If C is the class {@code Object}, or if C is an interface, then - * the superinterfaces of C (if any) are searched for a matching - * method. If any such method is found, it is reflected.</LI> - * </OL></LI> - * </OL> - * - * <p> To find a matching method in a class or interface C: If C - * declares exactly one public method with the specified name and exactly - * the same formal parameter types, that is the method reflected. If more - * than one such method is found in C, and one of these methods has a - * return type that is more specific than any of the others, that method is - * reflected; otherwise one of the methods is chosen arbitrarily. - * - * <p>Note that there may be more than one matching method in a - * class because while the Java language forbids a class to - * declare multiple methods with the same signature but different - * return types, the Java virtual machine does not. This - * increased flexibility in the virtual machine can be used to - * implement various language features. For example, covariant - * returns can be implemented with {@linkplain - * java.lang.reflect.Method#isBridge bridge methods}; the bridge - * method and the method being overridden would have the same - * signature but different return types. - * - * <p> If this {@code Class} object represents an array type, then this - * method does not find the {@code clone()} method. - * - * <p> Static methods declared in superinterfaces of the class or interface - * represented by this {@code Class} object are not considered members of - * the class or interface. - * - * @param name the name of the method - * @param parameterTypes the list of parameters - * @return the {@code Method} object that matches the specified - * {@code name} and {@code parameterTypes} - * @throws NoSuchMethodException if a matching method is not found - * or if the name is "<init>"or "<clinit>". - * @throws NullPointerException if {@code name} is {@code null} - * @throws SecurityException - * If a security manager, <i>s</i>, is present and - * the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class. - * - * @jls 8.2 Class Members - * @jls 8.4 Method Declarations - * @since JDK1.1 - */ - @CallerSensitive - public Method getMethod(String name, Class<?>... parameterTypes) - throws NoSuchMethodException, SecurityException { - checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); - Method method = getMethod0(name, parameterTypes, true); - if (method == null) { - throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); - } - return method; - } - - - /** - * Returns a {@code Constructor} object that reflects the specified - * public constructor of the class represented by this {@code Class} - * object. The {@code parameterTypes} parameter is an array of - * {@code Class} objects that identify the constructor's formal - * parameter types, in declared order. - * - * If this {@code Class} object represents an inner class - * declared in a non-static context, the formal parameter types - * include the explicit enclosing instance as the first parameter. - * - * <p> The constructor to reflect is the public constructor of the class - * represented by this {@code Class} object whose formal parameter - * types match those specified by {@code parameterTypes}. - * - * @param parameterTypes the parameter array - * @return the {@code Constructor} object of the public constructor that - * matches the specified {@code parameterTypes} - * @throws NoSuchMethodException if a matching method is not found. - * @throws SecurityException - * If a security manager, <i>s</i>, is present and - * the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class. - * - * @since JDK1.1 - */ - @CallerSensitive - public Constructor<T> getConstructor(Class<?>... parameterTypes) - throws NoSuchMethodException, SecurityException { - checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); - return getConstructor0(parameterTypes, Member.PUBLIC); - } - - - /** - * Returns an array of {@code Class} objects reflecting all the - * classes and interfaces declared as members of the class represented by - * this {@code Class} object. This includes public, protected, default - * (package) access, and private classes and interfaces declared by the - * class, but excludes inherited classes and interfaces. This method - * returns an array of length 0 if the class declares no classes or - * interfaces as members, or if this {@code Class} object represents a - * primitive type, an array class, or void. - * - * @return the array of {@code Class} objects representing all the - * declared members of this class - * @throws SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: - * - * <ul> - * - * <li> the caller's class loader is not the same as the - * class loader of this class and invocation of - * {@link SecurityManager#checkPermission - * s.checkPermission} method with - * {@code RuntimePermission("accessDeclaredMembers")} - * denies access to the declared classes within this class - * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class - * - * </ul> - * - * @since JDK1.1 - */ - @CallerSensitive - public Class<?>[] getDeclaredClasses() throws SecurityException { - checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), false); - return getDeclaredClasses0(); - } - - - /** - * Returns an array of {@code Field} objects reflecting all the fields - * declared by the class or interface represented by this - * {@code Class} object. This includes public, protected, default - * (package) access, and private fields, but excludes inherited fields. - * - * <p> If this {@code Class} object represents a class or interface with no - * declared fields, then this method returns an array of length 0. - * - * <p> If this {@code Class} object represents an array type, a primitive - * type, or void, then this method returns an array of length 0. - * - * <p> The elements in the returned array are not sorted and are not in any - * particular order. - * - * @return the array of {@code Field} objects representing all the - * declared fields of this class - * @throws SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: - * - * <ul> - * - * <li> the caller's class loader is not the same as the - * class loader of this class and invocation of - * {@link SecurityManager#checkPermission - * s.checkPermission} method with - * {@code RuntimePermission("accessDeclaredMembers")} - * denies access to the declared fields within this class - * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class - * - * </ul> - * - * @since JDK1.1 - * @jls 8.2 Class Members - * @jls 8.3 Field Declarations - */ - @CallerSensitive - public Field[] getDeclaredFields() throws SecurityException { - checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); - return copyFields(privateGetDeclaredFields(false)); - } - - - /** - * - * Returns an array containing {@code Method} objects reflecting all the - * declared methods of the class or interface represented by this {@code - * Class} object, including public, protected, default (package) - * access, and private methods, but excluding inherited methods. - * - * <p> If this {@code Class} object represents a type that has multiple - * declared methods with the same name and parameter types, but different - * return types, then the returned array has a {@code Method} object for - * each such method. - * - * <p> If this {@code Class} object represents a type that has a class - * initialization method {@code <clinit>}, then the returned array does - * <em>not</em> have a corresponding {@code Method} object. - * - * <p> If this {@code Class} object represents a class or interface with no - * declared methods, then the returned array has length 0. - * - * <p> If this {@code Class} object represents an array type, a primitive - * type, or void, then the returned array has length 0. - * - * <p> The elements in the returned array are not sorted and are not in any - * particular order. - * - * @return the array of {@code Method} objects representing all the - * declared methods of this class - * @throws SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: - * - * <ul> - * - * <li> the caller's class loader is not the same as the - * class loader of this class and invocation of - * {@link SecurityManager#checkPermission - * s.checkPermission} method with - * {@code RuntimePermission("accessDeclaredMembers")} - * denies access to the declared methods within this class - * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class - * - * </ul> - * - * @jls 8.2 Class Members - * @jls 8.4 Method Declarations - * @since JDK1.1 - */ - @CallerSensitive - public Method[] getDeclaredMethods() throws SecurityException { - checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); - return copyMethods(privateGetDeclaredMethods(false)); - } - - - /** - * Returns an array of {@code Constructor} objects reflecting all the - * constructors declared by the class represented by this - * {@code Class} object. These are public, protected, default - * (package) access, and private constructors. The elements in the array - * returned are not sorted and are not in any particular order. If the - * class has a default constructor, it is included in the returned array. - * This method returns an array of length 0 if this {@code Class} - * object represents an interface, a primitive type, an array class, or - * void. - * - * <p> See <em>The Java Language Specification</em>, section 8.2. - * - * @return the array of {@code Constructor} objects representing all the - * declared constructors of this class - * @throws SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: - * - * <ul> - * - * <li> the caller's class loader is not the same as the - * class loader of this class and invocation of - * {@link SecurityManager#checkPermission - * s.checkPermission} method with - * {@code RuntimePermission("accessDeclaredMembers")} - * denies access to the declared constructors within this class - * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class - * - * </ul> - * - * @since JDK1.1 - */ - @CallerSensitive - public Constructor<?>[] getDeclaredConstructors() throws SecurityException { - checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); - return copyConstructors(privateGetDeclaredConstructors(false)); - } - - - /** - * Returns a {@code Field} object that reflects the specified declared - * field of the class or interface represented by this {@code Class} - * object. The {@code name} parameter is a {@code String} that specifies - * the simple name of the desired field. - * - * <p> If this {@code Class} object represents an array type, then this - * method does not find the {@code length} field of the array type. - * - * @param name the name of the field - * @return the {@code Field} object for the specified field in this - * class - * @throws NoSuchFieldException if a field with the specified name is - * not found. - * @throws NullPointerException if {@code name} is {@code null} - * @throws SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: - * - * <ul> - * - * <li> the caller's class loader is not the same as the - * class loader of this class and invocation of - * {@link SecurityManager#checkPermission - * s.checkPermission} method with - * {@code RuntimePermission("accessDeclaredMembers")} - * denies access to the declared field - * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class - * - * </ul> - * - * @since JDK1.1 - * @jls 8.2 Class Members - * @jls 8.3 Field Declarations - */ - @CallerSensitive - public Field getDeclaredField(String name) - throws NoSuchFieldException, SecurityException { - checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); - Field field = searchFields(privateGetDeclaredFields(false), name); - if (field == null) { - throw new NoSuchFieldException(name); - } - return field; - } - - - /** - * Returns a {@code Method} object that reflects the specified - * declared method of the class or interface represented by this - * {@code Class} object. The {@code name} parameter is a - * {@code String} that specifies the simple name of the desired - * method, and the {@code parameterTypes} parameter is an array of - * {@code Class} objects that identify the method's formal parameter - * types, in declared order. If more than one method with the same - * parameter types is declared in a class, and one of these methods has a - * return type that is more specific than any of the others, that method is - * returned; otherwise one of the methods is chosen arbitrarily. If the - * name is "<init>"or "<clinit>" a {@code NoSuchMethodException} - * is raised. - * - * <p> If this {@code Class} object represents an array type, then this - * method does not find the {@code clone()} method. - * - * @param name the name of the method - * @param parameterTypes the parameter array - * @return the {@code Method} object for the method of this class - * matching the specified name and parameters - * @throws NoSuchMethodException if a matching method is not found. - * @throws NullPointerException if {@code name} is {@code null} - * @throws SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: - * - * <ul> - * - * <li> the caller's class loader is not the same as the - * class loader of this class and invocation of - * {@link SecurityManager#checkPermission - * s.checkPermission} method with - * {@code RuntimePermission("accessDeclaredMembers")} - * denies access to the declared method - * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class - * - * </ul> - * - * @jls 8.2 Class Members - * @jls 8.4 Method Declarations - * @since JDK1.1 - */ - @CallerSensitive - public Method getDeclaredMethod(String name, Class<?>... parameterTypes) - throws NoSuchMethodException, SecurityException { - checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); - Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes); - if (method == null) { - throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); - } - return method; - } - - - /** - * Returns a {@code Constructor} object that reflects the specified - * constructor of the class or interface represented by this - * {@code Class} object. The {@code parameterTypes} parameter is - * an array of {@code Class} objects that identify the constructor's - * formal parameter types, in declared order. - * - * If this {@code Class} object represents an inner class - * declared in a non-static context, the formal parameter types - * include the explicit enclosing instance as the first parameter. - * - * @param parameterTypes the parameter array - * @return The {@code Constructor} object for the constructor with the - * specified parameter list - * @throws NoSuchMethodException if a matching method is not found. - * @throws SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: - * - * <ul> - * - * <li> the caller's class loader is not the same as the - * class loader of this class and invocation of - * {@link SecurityManager#checkPermission - * s.checkPermission} method with - * {@code RuntimePermission("accessDeclaredMembers")} - * denies access to the declared constructor - * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class - * - * </ul> - * - * @since JDK1.1 - */ - @CallerSensitive - public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) - throws NoSuchMethodException, SecurityException { - checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); - return getConstructor0(parameterTypes, Member.DECLARED); - } - - /** - * Finds a resource with a given name. The rules for searching resources - * associated with a given class are implemented by the defining - * {@linkplain ClassLoader class loader} of the class. This method - * delegates to this object's class loader. If this object was loaded by - * the bootstrap class loader, the method delegates to {@link - * ClassLoader#getSystemResourceAsStream}. - * - * <p> Before delegation, an absolute resource name is constructed from the - * given resource name using this algorithm: - * - * <ul> - * - * <li> If the {@code name} begins with a {@code '/'} - * (<tt>'\u002f'</tt>), then the absolute name of the resource is the - * portion of the {@code name} following the {@code '/'}. - * - * <li> Otherwise, the absolute name is of the following form: - * - * <blockquote> - * {@code modified_package_name/name} - * </blockquote> - * - * <p> Where the {@code modified_package_name} is the package name of this - * object with {@code '/'} substituted for {@code '.'} - * (<tt>'\u002e'</tt>). - * - * </ul> - * - * @param name name of the desired resource - * @return A {@link java.io.InputStream} object or {@code null} if - * no resource with this name is found - * @throws NullPointerException If {@code name} is {@code null} - * @since JDK1.1 - */ - public InputStream getResourceAsStream(String name) { - name = resolveName(name); - ClassLoader cl = getClassLoader0(); - if (cl==null) { - // A system class. - return ClassLoader.getSystemResourceAsStream(name); - } - return cl.getResourceAsStream(name); - } - - /** - * Finds a resource with a given name. The rules for searching resources - * associated with a given class are implemented by the defining - * {@linkplain ClassLoader class loader} of the class. This method - * delegates to this object's class loader. If this object was loaded by - * the bootstrap class loader, the method delegates to {@link - * ClassLoader#getSystemResource}. - * - * <p> Before delegation, an absolute resource name is constructed from the - * given resource name using this algorithm: - * - * <ul> - * - * <li> If the {@code name} begins with a {@code '/'} - * (<tt>'\u002f'</tt>), then the absolute name of the resource is the - * portion of the {@code name} following the {@code '/'}. - * - * <li> Otherwise, the absolute name is of the following form: - * - * <blockquote> - * {@code modified_package_name/name} - * </blockquote> - * - * <p> Where the {@code modified_package_name} is the package name of this - * object with {@code '/'} substituted for {@code '.'} - * (<tt>'\u002e'</tt>). - * - * </ul> - * - * @param name name of the desired resource - * @return A {@link java.net.URL} object or {@code null} if no - * resource with this name is found - * @since JDK1.1 - */ - public java.net.URL getResource(String name) { - name = resolveName(name); - ClassLoader cl = getClassLoader0(); - if (cl==null) { - // A system class. - return ClassLoader.getSystemResource(name); - } - return cl.getResource(name); - } - - - - /** protection domain returned when the internal domain is null */ - private static java.security.ProtectionDomain allPermDomain; - - - /** - * Returns the {@code ProtectionDomain} of this class. If there is a - * security manager installed, this method first calls the security - * manager's {@code checkPermission} method with a - * {@code RuntimePermission("getProtectionDomain")} permission to - * ensure it's ok to get the - * {@code ProtectionDomain}. - * - * @return the ProtectionDomain of this class - * - * @throws SecurityException - * if a security manager exists and its - * {@code checkPermission} method doesn't allow - * getting the ProtectionDomain. - * - * @see java.security.ProtectionDomain - * @see SecurityManager#checkPermission - * @see java.lang.RuntimePermission - * @since 1.2 - */ - public java.security.ProtectionDomain getProtectionDomain() { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SecurityConstants.GET_PD_PERMISSION); - } - java.security.ProtectionDomain pd = getProtectionDomain0(); - if (pd == null) { - if (allPermDomain == null) { - java.security.Permissions perms = - new java.security.Permissions(); - perms.add(SecurityConstants.ALL_PERMISSION); - allPermDomain = - new java.security.ProtectionDomain(null, perms); - } - pd = allPermDomain; - } - return pd; - } - - - /** - * Returns the ProtectionDomain of this class. - */ - private native java.security.ProtectionDomain getProtectionDomain0(); - - /* - * Return the Virtual Machine's Class object for the named - * primitive type. - */ - static native Class<?> getPrimitiveClass(String name); - - /* - * Check if client is allowed to access members. If access is denied, - * throw a SecurityException. - * - * This method also enforces package access. - * - * <p> Default policy: allow all clients access with normal Java access - * control. - */ - private void checkMemberAccess(int which, Class<?> caller, boolean checkProxyInterfaces) { - final SecurityManager s = System.getSecurityManager(); - if (s != null) { - /* Default policy allows access to all {@link Member#PUBLIC} members, - * as well as access to classes that have the same class loader as the caller. - * In all other cases, it requires RuntimePermission("accessDeclaredMembers") - * permission. - */ - final ClassLoader ccl = ClassLoader.getClassLoader(caller); - final ClassLoader cl = getClassLoader0(); - if (which != Member.PUBLIC) { - if (ccl != cl) { - s.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); - } - } - this.checkPackageAccess(ccl, checkProxyInterfaces); - } - } - - /* - * Checks if a client loaded in ClassLoader ccl is allowed to access this - * class under the current package access policy. If access is denied, - * throw a SecurityException. - */ - private void checkPackageAccess(final ClassLoader ccl, boolean checkProxyInterfaces) { - final SecurityManager s = System.getSecurityManager(); - if (s != null) { - final ClassLoader cl = getClassLoader0(); - - if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) { - String name = this.getName(); - int i = name.lastIndexOf('.'); - if (i != -1) { - // skip the package access check on a proxy class in default proxy package - String pkg = name.substring(0, i); - if (!Proxy.isProxyClass(this) || ReflectUtil.isNonPublicProxyClass(this)) { - s.checkPackageAccess(pkg); - } - } - } - // check package access on the proxy interfaces - if (checkProxyInterfaces && Proxy.isProxyClass(this)) { - ReflectUtil.checkProxyPackageAccess(ccl, this.getInterfaces()); - } - } - } - - /** - * Add a package name prefix if the name is not absolute Remove leading "/" - * if name is absolute - */ - private String resolveName(String name) { - if (name == null) { - return name; - } - if (!name.startsWith("/")) { - Class<?> c = this; - while (c.isArray()) { - c = c.getComponentType(); - } - String baseName = c.getName(); - int index = baseName.lastIndexOf('.'); - if (index != -1) { - name = baseName.substring(0, index).replace('.', '/') - +"/"+name; - } - } else { - name = name.substring(1); - } - return name; - } - - /** - * Atomic operations support. - */ - private static class Atomic { - @ikvm.internal.InterlockedCompareAndSet("reflectionData") - static native <T> boolean casReflectionData(Class<?> clazz, - SoftReference<ReflectionData<T>> oldData, - SoftReference<ReflectionData<T>> newData); - - @ikvm.internal.InterlockedCompareAndSet("annotationType") - static native <T> boolean casAnnotationType(Class<?> clazz, - AnnotationType oldType, - AnnotationType newType); - - @ikvm.internal.InterlockedCompareAndSet("annotationData") - static native <T> boolean casAnnotationData(Class<?> clazz, - AnnotationData oldData, - AnnotationData newData); - } - - /** - * Reflection support. - */ - - // Caches for certain reflective results - private static boolean useCaches; - - // reflection data that might get invalidated when JVM TI RedefineClasses() is called - private static class ReflectionData<T> { - volatile Field[] declaredFields; - volatile Field[] publicFields; - volatile Method[] declaredMethods; - volatile Method[] publicMethods; - volatile Constructor<T>[] declaredConstructors; - volatile Constructor<T>[] publicConstructors; - // Intermediate results for getFields and getMethods - volatile Field[] declaredPublicFields; - volatile Method[] declaredPublicMethods; - volatile Class<?>[] interfaces; - - // Value of classRedefinedCount when we created this ReflectionData instance - final int redefinedCount; - - ReflectionData(int redefinedCount) { - this.redefinedCount = redefinedCount; - } - } - - private volatile transient SoftReference<ReflectionData<T>> reflectionData; - - // Incremented by the VM on each call to JVM TI RedefineClasses() - // that redefines this class or a superclass. - private volatile transient int classRedefinedCount; - - // Lazily create and cache ReflectionData - private ReflectionData<T> reflectionData() { - SoftReference<ReflectionData<T>> reflectionData = this.reflectionData; - int classRedefinedCount = this.classRedefinedCount; - ReflectionData<T> rd; - if (useCaches && - reflectionData != null && - (rd = reflectionData.get()) != null && - rd.redefinedCount == classRedefinedCount) { - return rd; - } - // else no SoftReference or cleared SoftReference or stale ReflectionData - // -> create and replace new instance - return newReflectionData(reflectionData, classRedefinedCount); - } - - private ReflectionData<T> newReflectionData(SoftReference<ReflectionData<T>> oldReflectionData, - int classRedefinedCount) { - if (!useCaches) return null; - - while (true) { - ReflectionData<T> rd = new ReflectionData<>(classRedefinedCount); - // try to CAS it... - if (Atomic.casReflectionData(this, oldReflectionData, new SoftReference<>(rd))) { - return rd; - } - // else retry - oldReflectionData = this.reflectionData; - classRedefinedCount = this.classRedefinedCount; - if (oldReflectionData != null && - (rd = oldReflectionData.get()) != null && - rd.redefinedCount == classRedefinedCount) { - return rd; - } - } - } - - // Generic signature handling - private native String getGenericSignature0(); - - // Generic info repository; lazily initialized - private volatile transient ClassRepository genericInfo; - - // accessor for factory - private GenericsFactory getFactory() { - // create scope and factory - return CoreReflectionFactory.make(this, ClassScope.make(this)); - } - - // accessor for generic info repository; - // generic info is lazily initialized - private ClassRepository getGenericInfo() { - ClassRepository genericInfo = this.genericInfo; - if (genericInfo == null) { - String signature = getGenericSignature0(); - if (signature == null) { - genericInfo = ClassRepository.NONE; - } else { - genericInfo = ClassRepository.make(signature, getFactory()); - } - this.genericInfo = genericInfo; - } - return (genericInfo != ClassRepository.NONE) ? genericInfo : null; - } - - // Annotations handling - private native Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationsImpl(); - // Since 1.8 - native byte[] getRawTypeAnnotations(); - static byte[] getExecutableTypeAnnotationBytes(Executable ex) { - return getReflectionFactory().getExecutableTypeAnnotationBytes(ex); - } - - native ConstantPool getConstantPool(); - - // - // - // java.lang.reflect.Field handling - // - // - - // Returns an array of "root" fields. These Field objects must NOT - // be propagated to the outside world, but must instead be copied - // via ReflectionFactory.copyField. - private Field[] privateGetDeclaredFields(boolean publicOnly) { - checkInitted(); - Field[] res; - ReflectionData<T> rd = reflectionData(); - if (rd != null) { - res = publicOnly ? rd.declaredPublicFields : rd.declaredFields; - if (res != null) return res; - } - // No cached value available; request value from VM - res = Reflection.filterFields(this, getDeclaredFields0(publicOnly)); - if (rd != null) { - if (publicOnly) { - rd.declaredPublicFields = res; - } else { - rd.declaredFields = res; - } - } - return res; - } - - // Returns an array of "root" fields. These Field objects must NOT - // be propagated to the outside world, but must instead be copied - // via ReflectionFactory.copyField. - private Field[] privateGetPublicFields(Set<Class<?>> traversedInterfaces) { - checkInitted(); - Field[] res; - ReflectionData<T> rd = reflectionData(); - if (rd != null) { - res = rd.publicFields; - if (res != null) return res; - } - - // No cached value available; compute value recursively. - // Traverse in correct order for getField(). - List<Field> fields = new ArrayList<>(); - if (traversedInterfaces == null) { - traversedInterfaces = new HashSet<>(); - } - - // Local fields - Field[] tmp = privateGetDeclaredFields(true); - addAll(fields, tmp); - - // Direct superinterfaces, recursively - for (Class<?> c : getInterfaces()) { - if (!traversedInterfaces.contains(c)) { - traversedInterfaces.add(c); - addAll(fields, c.privateGetPublicFields(traversedInterfaces)); - } - } - - // Direct superclass, recursively - if (!isInterface()) { - Class<?> c = getSuperclass(); - if (c != null) { - addAll(fields, c.privateGetPublicFields(traversedInterfaces)); - } - } - - res = new Field[fields.size()]; - fields.toArray(res); - if (rd != null) { - rd.publicFields = res; - } - return res; - } - - private static void addAll(Collection<Field> c, Field[] o) { - for (int i = 0; i < o.length; i++) { - c.add(o[i]); - } - } - - - // - // - // java.lang.reflect.Constructor handling - // - // - - // Returns an array of "root" constructors. These Constructor - // objects must NOT be propagated to the outside world, but must - // instead be copied via ReflectionFactory.copyConstructor. - private Constructor<T>[] privateGetDeclaredConstructors(boolean publicOnly) { - checkInitted(); - Constructor<T>[] res; - ReflectionData<T> rd = reflectionData(); - if (rd != null) { - res = publicOnly ? rd.publicConstructors : rd.declaredConstructors; - if (res != null) return res; - } - // No cached value available; request value from VM - if (isInterface()) { - @SuppressWarnings("unchecked") - Constructor<T>[] temporaryRes = (Constructor<T>[]) new Constructor<?>[0]; - res = temporaryRes; - } else { - res = getDeclaredConstructors0(publicOnly); - } - if (rd != null) { - if (publicOnly) { - rd.publicConstructors = res; - } else { - rd.declaredConstructors = res; - } - } - return res; - } - - // - // - // java.lang.reflect.Method handling - // - // - - // Returns an array of "root" methods. These Method objects must NOT - // be propagated to the outside world, but must instead be copied - // via ReflectionFactory.copyMethod. - private Method[] privateGetDeclaredMethods(boolean publicOnly) { - checkInitted(); - Method[] res; - ReflectionData<T> rd = reflectionData(); - if (rd != null) { - res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods; - if (res != null) return res; - } - // No cached value available; request value from VM - res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly)); - if (rd != null) { - if (publicOnly) { - rd.declaredPublicMethods = res; - } else { - rd.declaredMethods = res; - } - } - return res; - } - - static class MethodArray { - private Method[] methods; - private int length; - - MethodArray() { - methods = new Method[20]; - length = 0; - } - - void add(Method m) { - if (length == methods.length) { - methods = Arrays.copyOf(methods, 2 * methods.length); - } - methods[length++] = m; - } - - void addAll(Method[] ma) { - for (int i = 0; i < ma.length; i++) { - add(ma[i]); - } - } - - void addAll(MethodArray ma) { - for (int i = 0; i < ma.length(); i++) { - add(ma.get(i)); - } - } - - void addIfNotPresent(Method newMethod) { - for (int i = 0; i < length; i++) { - Method m = methods[i]; - if (m == newMethod || (m != null && m.equals(newMethod))) { - return; - } - } - add(newMethod); - } - - void addAllIfNotPresent(MethodArray newMethods) { - for (int i = 0; i < newMethods.length(); i++) { - Method m = newMethods.get(i); - if (m != null) { - addIfNotPresent(m); - } - } - } - - void addAllNonStatic(Method[] methods) { - for (Method candidate : methods) { - if (!Modifier.isStatic(candidate.getModifiers())) { - add(candidate); - } - } - } - - int length() { - return length; - } - - Method get(int i) { - return methods[i]; - } - - void removeByNameAndSignature(Method toRemove) { - for (int i = 0; i < length; i++) { - Method m = methods[i]; - if (m != null && - m.getReturnType() == toRemove.getReturnType() && - m.getName() == toRemove.getName() && - arrayContentsEq(m.getParameterTypes(), - toRemove.getParameterTypes())) { - methods[i] = null; - } - } - } - - void compactAndTrim() { - int newPos = 0; - // Get rid of null slots - for (int pos = 0; pos < length; pos++) { - Method m = methods[pos]; - if (m != null) { - if (pos != newPos) { - methods[newPos] = m; - } - newPos++; - } - } - if (newPos != methods.length) { - methods = Arrays.copyOf(methods, newPos); - } - } - - Method[] getArray() { - return methods; - } - } - - - // Returns an array of "root" methods. These Method objects must NOT - // be propagated to the outside world, but must instead be copied - // via ReflectionFactory.copyMethod. - private Method[] privateGetPublicMethods() { - checkInitted(); - Method[] res; - ReflectionData<T> rd = reflectionData(); - if (rd != null) { - res = rd.publicMethods; - if (res != null) return res; - } - - // No cached value available; compute value recursively. - // Start by fetching public declared methods - MethodArray methods = new MethodArray(); - { - Method[] tmp = privateGetDeclaredMethods(true); - methods.addAll(tmp); - } - // Now recur over superclass and direct superinterfaces. - // Go over superinterfaces first so we can more easily filter - // out concrete implementations inherited from superclasses at - // the end. - MethodArray inheritedMethods = new MethodArray(); - Class<?>[] interfaces = getInterfaces(); - for (int i = 0; i < interfaces.length; i++) { - inheritedMethods.addAllNonStatic(interfaces[i].privateGetPublicMethods()); - } - if (!isInterface()) { - Class<?> c = getSuperclass(); - if (c != null) { - MethodArray supers = new MethodArray(); - supers.addAll(c.privateGetPublicMethods()); - // Filter out concrete implementations of any - // interface methods - for (int i = 0; i < supers.length(); i++) { - Method m = supers.get(i); - if (m != null && !Modifier.isAbstract(m.getModifiers())) { - inheritedMethods.removeByNameAndSignature(m); - } - } - // Insert superclass's inherited methods before - // superinterfaces' to satisfy getMethod's search - // order - supers.addAll(inheritedMethods); - inheritedMethods = supers; - } - } - // Filter out all local methods from inherited ones - for (int i = 0; i < methods.length(); i++) { - Method m = methods.get(i); - inheritedMethods.removeByNameAndSignature(m); - } - methods.addAllIfNotPresent(inheritedMethods); - methods.compactAndTrim(); - res = methods.getArray(); - if (rd != null) { - rd.publicMethods = res; - } - return res; - } - - - // - // Helpers for fetchers of one field, method, or constructor - // - - private static Field searchFields(Field[] fields, String name) { - String internedName = name.intern(); - for (int i = 0; i < fields.length; i++) { - if (fields[i].getName() == internedName) { - return getReflectionFactory().copyField(fields[i]); - } - } - return null; - } - - private Field getField0(String name) throws NoSuchFieldException { - // Note: the intent is that the search algorithm this routine - // uses be equivalent to the ordering imposed by - // privateGetPublicFields(). It fetches only the declared - // public fields for each class, however, to reduce the number - // of Field objects which have to be created for the common - // case where the field being requested is declared in the - // class which is being queried. - Field res; - // Search declared public fields - if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) { - return res; - } - // Direct superinterfaces, recursively - Class<?>[] interfaces = getInterfaces(); - for (int i = 0; i < interfaces.length; i++) { - Class<?> c = interfaces[i]; - if ((res = c.getField0(name)) != null) { - return res; - } - } - // Direct superclass, recursively - if (!isInterface()) { - Class<?> c = getSuperclass(); - if (c != null) { - if ((res = c.getField0(name)) != null) { - return res; - } - } - } - return null; - } - - private static Method searchMethods(Method[] methods, - String name, - Class<?>[] parameterTypes) - { - Method res = null; - String internedName = name.intern(); - for (int i = 0; i < methods.length; i++) { - Method m = methods[i]; - if (m.getName() == internedName - && arrayContentsEq(parameterTypes, m.getParameterTypes()) - && (res == null - || res.getReturnType().isAssignableFrom(m.getReturnType()))) - res = m; - } - - return (res == null ? res : getReflectionFactory().copyMethod(res)); - } - - - private Method getMethod0(String name, Class<?>[] parameterTypes, boolean includeStaticMethods) { - // Note: the intent is that the search algorithm this routine - // uses be equivalent to the ordering imposed by - // privateGetPublicMethods(). It fetches only the declared - // public methods for each class, however, to reduce the - // number of Method objects which have to be created for the - // common case where the method being requested is declared in - // the class which is being queried. - Method res; - // Search declared public methods - if ((res = searchMethods(privateGetDeclaredMethods(true), - name, - parameterTypes)) != null) { - if (includeStaticMethods || !Modifier.isStatic(res.getModifiers())) - return res; - } - // Search superclass's methods - if (!isInterface()) { - Class<? super T> c = getSuperclass(); - if (c != null) { - if ((res = c.getMethod0(name, parameterTypes, true)) != null) { - return res; - } - } - } - // Search superinterfaces' methods - Class<?>[] interfaces = getInterfaces(); - for (Class<?> c : interfaces) - if ((res = c.getMethod0(name, parameterTypes, false)) != null) - return res; - // Not found - return null; - } - - private Constructor<T> getConstructor0(Class<?>[] parameterTypes, - int which) throws NoSuchMethodException - { - Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC)); - for (Constructor<T> constructor : constructors) { - if (arrayContentsEq(parameterTypes, - constructor.getParameterTypes())) { - return getReflectionFactory().copyConstructor(constructor); - } - } - throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes)); - } - - // - // Other helpers and base implementation - // - - private static boolean arrayContentsEq(Object[] a1, Object[] a2) { - if (a1 == null) { - return a2 == null || a2.length == 0; - } - - if (a2 == null) { - return a1.length == 0; - } - - if (a1.length != a2.length) { - return false; - } - - for (int i = 0; i < a1.length; i++) { - if (a1[i] != a2[i]) { - return false; - } - } - - return true; - } - - private static Field[] copyFields(Field[] arg) { - Field[] out = new Field[arg.length]; - ReflectionFactory fact = getReflectionFactory(); - for (int i = 0; i < arg.length; i++) { - out[i] = fact.copyField(arg[i]); - } - return out; - } - - private static Method[] copyMethods(Method[] arg) { - Method[] out = new Method[arg.length]; - ReflectionFactory fact = getReflectionFactory(); - for (int i = 0; i < arg.length; i++) { - out[i] = fact.copyMethod(arg[i]); - } - return out; - } - - private static <U> Constructor<U>[] copyConstructors(Constructor<U>[] arg) { - Constructor<U>[] out = arg.clone(); - ReflectionFactory fact = getReflectionFactory(); - for (int i = 0; i < out.length; i++) { - out[i] = fact.copyConstructor(out[i]); - } - return out; - } - - private native Field[] getDeclaredFields0(boolean publicOnly); - private native Method[] getDeclaredMethods0(boolean publicOnly); - private native Constructor<T>[] getDeclaredConstructors0(boolean publicOnly); - private native Class<?>[] getDeclaredClasses0(); - - private static String argumentTypesToString(Class<?>[] argTypes) { - StringBuilder buf = new StringBuilder(); - buf.append("("); - if (argTypes != null) { - for (int i = 0; i < argTypes.length; i++) { - if (i > 0) { - buf.append(", "); - } - Class<?> c = argTypes[i]; - buf.append((c == null) ? "null" : c.getName()); - } - } - buf.append(")"); - return buf.toString(); - } - - /** use serialVersionUID from JDK 1.1 for interoperability */ - private static final long serialVersionUID = 3206093459760846163L; - - - /** - * Class Class is special cased within the Serialization Stream Protocol. - * - * A Class instance is written initially into an ObjectOutputStream in the - * following format: - * <pre> - * {@code TC_CLASS} ClassDescriptor - * A ClassDescriptor is a special cased serialization of - * a {@code java.io.ObjectStreamClass} instance. - * </pre> - * A new handle is generated for the initial time the class descriptor - * is written into the stream. Future references to the class descriptor - * are written as references to the initial class descriptor instance. - * - * @see java.io.ObjectStreamClass - */ - - @ikvm.lang.Property(get="get_spf") - private static final ObjectStreamField[] serialPersistentFields = null; - - private static ObjectStreamField[] get_spf() { - return java.io.ObjectStreamClass.NO_FIELDS; - } - - - /** - * Returns the assertion status that would be assigned to this - * class if it were to be initialized at the time this method is invoked. - * If this class has had its assertion status set, the most recent - * setting will be returned; otherwise, if any package default assertion - * status pertains to this class, the most recent setting for the most - * specific pertinent package default assertion status is returned; - * otherwise, if this class is not a system class (i.e., it has a - * class loader) its class loader's default assertion status is returned; - * otherwise, the system class default assertion status is returned. - * <p> - * Few programmers will have any need for this method; it is provided - * for the benefit of the JRE itself. (It allows a class to determine at - * the time that it is initialized whether assertions should be enabled.) - * Note that this method is not guaranteed to return the actual - * assertion status that was (or will be) associated with the specified - * class when it was (or will be) initialized. - * - * @return the desired assertion status of the specified class. - * @see java.lang.ClassLoader#setClassAssertionStatus - * @see java.lang.ClassLoader#setPackageAssertionStatus - * @see java.lang.ClassLoader#setDefaultAssertionStatus - * @since 1.4 - */ - public boolean desiredAssertionStatus() { - ClassLoader loader = getClassLoader(); - // If the loader is null this is a system class, so ask the VM - if (loader == null) - return desiredAssertionStatus0(this); - - // If the classloader has been initialized with the assertion - // directives, ask it. Otherwise, ask the VM. - synchronized(loader.assertionLock) { - if (loader.classAssertionStatus != null) { - return loader.desiredAssertionStatus(getName()); - } - } - return desiredAssertionStatus0(this); - } - - // Retrieves the desired assertion status of this class from the VM - private static native boolean desiredAssertionStatus0(Class<?> clazz); - - /** - * Returns true if and only if this class was declared as an enum in the - * source code. - * - * @return true if and only if this class was declared as an enum in the - * source code - * @since 1.5 - */ - public boolean isEnum() { - // An enum must both directly extend java.lang.Enum and have - // the ENUM bit set; classes for specialized enum constants - // don't do the former. - return (this.getModifiers() & ENUM) != 0 && - this.getSuperclass() == java.lang.Enum.class; - } - - // Fetches the factory for reflective objects - private static ReflectionFactory getReflectionFactory() { - if (reflectionFactory == null) { - reflectionFactory = - java.security.AccessController.doPrivileged - (new sun.reflect.ReflectionFactory.GetReflectionFactoryAction()); - } - return reflectionFactory; - } - private static ReflectionFactory reflectionFactory; - - // To be able to query system properties as soon as they're available - private static boolean initted; - private static void checkInitted() { - if (initted) return; - useCaches = true; - AccessController.doPrivileged(new PrivilegedAction<Void>() { - public Void run() { - // Tests to ensure the system properties table is fully - // initialized. This is needed because reflection code is - // called very early in the initialization process (before - // command-line arguments have been parsed and therefore - // these user-settable properties installed.) - - if (!sun.misc.VM.isBooted()) { - return null; - } - - // Doesn't use Boolean.getBoolean to avoid class init. - String val = - System.getProperty("sun.reflect.noCaches"); - if (val != null && val.equals("true")) { - useCaches = false; - } - - initted = true; - return null; - } - }); - } - - /** - * Returns the elements of this enum class or null if this - * Class object does not represent an enum type. - * - * @return an array containing the values comprising the enum class - * represented by this Class object in the order they're - * declared, or null if this Class object does not - * represent an enum type - * @since 1.5 - */ - public T[] getEnumConstants() { - T[] values = getEnumConstantsShared(); - return (values != null) ? values.clone() : null; - } - - /** - * Returns the elements of this enum class or null if this - * Class object does not represent an enum type; - * identical to getEnumConstants except that the result is - * uncloned, cached, and shared by all callers. - */ - T[] getEnumConstantsShared() { - if (enumConstants == null) { - if (!isEnum()) return null; - try { - final Method values = getMethod("values"); - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Void>() { - public Void run() { - values.setAccessible(true); - return null; - } - }); - @SuppressWarnings("unchecked") - T[] temporaryConstants = (T[])values.invoke(null); - enumConstants = temporaryConstants; - } - // These can happen when users concoct enum-like classes - // that don't comply with the enum spec. - catch (InvocationTargetException | NoSuchMethodException | - IllegalAccessException ex) { return null; } - } - return enumConstants; - } - private volatile transient T[] enumConstants; - - /** - * Returns a map from simple name to enum constant. This package-private - * method is used internally by Enum to implement - * {@code public static <T extends Enum<T>> T valueOf(Class<T>, String)} - * efficiently. Note that the map is returned by this method is - * created lazily on first use. Typically it won't ever get created. - */ - Map<String, T> enumConstantDirectory() { - if (enumConstantDirectory == null) { - T[] universe = getEnumConstantsShared(); - if (universe == null) - throw new IllegalArgumentException( - getName() + " is not an enum type"); - Map<String, T> m = new HashMap<>(2 * universe.length); - for (T constant : universe) - m.put(((Enum<?>)constant).name(), constant); - enumConstantDirectory = m; - } - return enumConstantDirectory; - } - private volatile transient Map<String, T> enumConstantDirectory; - - /** - * Casts an object to the class or interface represented - * by this {@code Class} object. - * - * @param obj the object to be cast - * @return the object after casting, or null if obj is null - * - * @throws ClassCastException if the object is not - * null and is not assignable to the type T. - * - * @since 1.5 - */ - @SuppressWarnings("unchecked") - public T cast(Object obj) { - if (obj != null && !isInstance(obj)) - throw new ClassCastException(cannotCastMsg(obj)); - return (T) obj; - } - - private String cannotCastMsg(Object obj) { - return "Cannot cast " + obj.getClass().getName() + " to " + getName(); - } - - /** - * Casts this {@code Class} object to represent a subclass of the class - * represented by the specified class object. Checks that the cast - * is valid, and throws a {@code ClassCastException} if it is not. If - * this method succeeds, it always returns a reference to this class object. - * - * <p>This method is useful when a client needs to "narrow" the type of - * a {@code Class} object to pass it to an API that restricts the - * {@code Class} objects that it is willing to accept. A cast would - * generate a compile-time warning, as the correctness of the cast - * could not be checked at runtime (because generic types are implemented - * by erasure). - * - * @param <U> the type to cast this class object to - * @param clazz the class of the type to cast this class object to - * @return this {@code Class} object, cast to represent a subclass of - * the specified class object. - * @throws ClassCastException if this {@code Class} object does not - * represent a subclass of the specified class (here "subclass" includes - * the class itself). - * @since 1.5 - */ - @SuppressWarnings("unchecked") - public <U> Class<? extends U> asSubclass(Class<U> clazz) { - if (clazz.isAssignableFrom(this)) - return (Class<? extends U>) this; - else - throw new ClassCastException(this.toString()); - } - - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.5 - */ - @SuppressWarnings("unchecked") - public <A extends Annotation> A getAnnotation(Class<A> annotationClass) { - Objects.requireNonNull(annotationClass); - - return (A) annotationData().annotations.get(annotationClass); - } - - /** - * {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - * @since 1.5 - */ - @Override - public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { - return GenericDeclaration.super.isAnnotationPresent(annotationClass); - } - - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.8 - */ - @Override - public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass) { - Objects.requireNonNull(annotationClass); - - AnnotationData annotationData = annotationData(); - return AnnotationSupport.getAssociatedAnnotations(annotationData.declaredAnnotations, - this, - annotationClass); - } - - /** - * @since 1.5 - */ - public Annotation[] getAnnotations() { - return AnnotationParser.toArray(annotationData().annotations); - } - - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.8 - */ - @Override - @SuppressWarnings("unchecked") - public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) { - Objects.requireNonNull(annotationClass); - - return (A) annotationData().declaredAnnotations.get(annotationClass); - } - - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.8 - */ - @Override - public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationClass) { - Objects.requireNonNull(annotationClass); - - return AnnotationSupport.getDirectlyAndIndirectlyPresent(annotationData().declaredAnnotations, - annotationClass); - } - - /** - * @since 1.5 - */ - public Annotation[] getDeclaredAnnotations() { - return AnnotationParser.toArray(annotationData().declaredAnnotations); - } - - // annotation data that might get invalidated when JVM TI RedefineClasses() is called - private static class AnnotationData { - final Map<Class<? extends Annotation>, Annotation> annotations; - final Map<Class<? extends Annotation>, Annotation> declaredAnnotations; - - // Value of classRedefinedCount when we created this AnnotationData instance - final int redefinedCount; - - AnnotationData(Map<Class<? extends Annotation>, Annotation> annotations, - Map<Class<? extends Annotation>, Annotation> declaredAnnotations, - int redefinedCount) { - this.annotations = annotations; - this.declaredAnnotations = declaredAnnotations; - this.redefinedCount = redefinedCount; - } - } - - // Annotations cache - @SuppressWarnings("UnusedDeclaration") - private volatile transient AnnotationData annotationData; - - private AnnotationData annotationData() { - while (true) { // retry loop - AnnotationData annotationData = this.annotationData; - int classRedefinedCount = this.classRedefinedCount; - if (annotationData != null && - annotationData.redefinedCount == classRedefinedCount) { - return annotationData; - } - // null or stale annotationData -> optimistically create new instance - AnnotationData newAnnotationData = createAnnotationData(classRedefinedCount); - // try to install it - if (Atomic.casAnnotationData(this, annotationData, newAnnotationData)) { - // successfully installed new AnnotationData - return newAnnotationData; - } - } - } - - private AnnotationData createAnnotationData(int classRedefinedCount) { - Map<Class<? extends Annotation>, Annotation> declaredAnnotations = - getDeclaredAnnotationsImpl(); - Class<?> superClass = getSuperclass(); - Map<Class<? extends Annotation>, Annotation> annotations = null; - if (superClass != null) { - Map<Class<? extends Annotation>, Annotation> superAnnotations = - superClass.annotationData().annotations; - for (Map.Entry<Class<? extends Annotation>, Annotation> e : superAnnotations.entrySet()) { - Class<? extends Annotation> annotationClass = e.getKey(); - if (AnnotationType.getInstance(annotationClass).isInherited()) { - if (annotations == null) { // lazy construction - annotations = new LinkedHashMap<>((Math.max( - declaredAnnotations.size(), - Math.min(12, declaredAnnotations.size() + superAnnotations.size()) - ) * 4 + 2) / 3 - ); - } - annotations.put(annotationClass, e.getValue()); - } - } - } - if (annotations == null) { - // no inherited annotations -> share the Map with declaredAnnotations - annotations = declaredAnnotations; - } else { - // at least one inherited annotation -> declared may override inherited - annotations.putAll(declaredAnnotations); - } - return new AnnotationData(annotations, declaredAnnotations, classRedefinedCount); - } - - // Annotation types cache their internal (AnnotationType) form - - @SuppressWarnings("UnusedDeclaration") - private volatile transient AnnotationType annotationType; - - boolean casAnnotationType(AnnotationType oldType, AnnotationType newType) { - return Atomic.casAnnotationType(this, oldType, newType); - } - - AnnotationType getAnnotationType() { - return annotationType; - } - - Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationMap() { - return annotationData().declaredAnnotations; - } - - /* Backing store of user-defined values pertaining to this class. - * Maintained by the ClassValue class. - */ - transient ClassValue.ClassValueMap classValueMap; - - /** - * Returns an {@code AnnotatedType} object that represents the use of a - * type to specify the superclass of the entity represented by this {@code - * Class} object. (The <em>use</em> of type Foo to specify the superclass - * in '... extends Foo' is distinct from the <em>declaration</em> of type - * Foo.) - * - * <p> If this {@code Class} object represents a type whose declaration - * does not explicitly indicate an annotated superclass, then the return - * value is an {@code AnnotatedType} object representing an element with no - * annotations. - * - * <p> If this {@code Class} represents either the {@code Object} class, an - * interface type, an array type, a primitive type, or void, the return - * value is {@code null}. - * - * @return an object representing the superclass - * @since 1.8 - */ - public AnnotatedType getAnnotatedSuperclass() { - if (this == Object.class || - isInterface() || - isArray() || - isPrimitive() || - this == Void.TYPE) { - return null; - } - - return TypeAnnotationParser.buildAnnotatedSuperclass(getRawTypeAnnotations(), getConstantPool(), this); - } - - /** - * Returns an array of {@code AnnotatedType} objects that represent the use - * of types to specify superinterfaces of the entity represented by this - * {@code Class} object. (The <em>use</em> of type Foo to specify a - * superinterface in '... implements Foo' is distinct from the - * <em>declaration</em> of type Foo.) - * - * <p> If this {@code Class} object represents a class, the return value is - * an array containing objects representing the uses of interface types to - * specify interfaces implemented by the class. The order of the objects in - * the array corresponds to the order of the interface types used in the - * 'implements' clause of the declaration of this {@code Class} object. - * - * <p> If this {@code Class} object represents an interface, the return - * value is an array containing objects representing the uses of interface - * types to specify interfaces directly extended by the interface. The - * order of the objects in the array corresponds to the order of the - * interface types used in the 'extends' clause of the declaration of this - * {@code Class} object. - * - * <p> If this {@code Class} object represents a class or interface whose - * declaration does not explicitly indicate any annotated superinterfaces, - * the return value is an array of length 0. - * - * <p> If this {@code Class} object represents either the {@code Object} - * class, an array type, a primitive type, or void, the return value is an - * array of length 0. - * - * @return an array representing the superinterfaces - * @since 1.8 - */ - public AnnotatedType[] getAnnotatedInterfaces() { - return TypeAnnotationParser.buildAnnotatedInterfaces(getRawTypeAnnotations(), getConstantPool(), this); - } -} diff --git a/openjdk/java/lang/ClassLoader.java b/openjdk/java/lang/ClassLoader.java deleted file mode 100644 index 57c1ee3e..00000000 --- a/openjdk/java/lang/ClassLoader.java +++ /dev/null @@ -1,2261 +0,0 @@ -/* - * Copyright (c) 1994, 2011, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package java.lang; - -import java.io.InputStream; -import java.io.IOException; -import java.io.File; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.net.MalformedURLException; -import java.net.URL; -import java.security.AccessController; -import java.security.AccessControlContext; -import java.security.CodeSource; -import java.security.Policy; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.security.ProtectionDomain; -import java.security.cert.Certificate; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; -import java.util.Stack; -import java.util.Map; -import java.util.Vector; -import java.util.Hashtable; -import java.util.WeakHashMap; -import java.util.concurrent.ConcurrentHashMap; -import sun.misc.ClassFileTransformer; -import sun.misc.CompoundEnumeration; -import sun.misc.Resource; -import sun.misc.URLClassPath; -import sun.misc.VM; -import sun.reflect.CallerSensitive; -import sun.reflect.Reflection; -import sun.security.util.SecurityConstants; - -/** - * A class loader is an object that is responsible for loading classes. The - * class <tt>ClassLoader</tt> is an abstract class. Given the <a - * href="#name">binary name</a> of a class, a class loader should attempt to - * locate or generate data that constitutes a definition for the class. A - * typical strategy is to transform the name into a file name and then read a - * "class file" of that name from a file system. - * - * <p> Every {@link Class <tt>Class</tt>} object contains a {@link - * Class#getClassLoader() reference} to the <tt>ClassLoader</tt> that defined - * it. - * - * <p> <tt>Class</tt> objects for array classes are not created by class - * loaders, but are created automatically as required by the Java runtime. - * The class loader for an array class, as returned by {@link - * Class#getClassLoader()} is the same as the class loader for its element - * type; if the element type is a primitive type, then the array class has no - * class loader. - * - * <p> Applications implement subclasses of <tt>ClassLoader</tt> in order to - * extend the manner in which the Java virtual machine dynamically loads - * classes. - * - * <p> Class loaders may typically be used by security managers to indicate - * security domains. - * - * <p> The <tt>ClassLoader</tt> class uses a delegation model to search for - * classes and resources. Each instance of <tt>ClassLoader</tt> has an - * associated parent class loader. When requested to find a class or - * resource, a <tt>ClassLoader</tt> instance will delegate the search for the - * class or resource to its parent class loader before attempting to find the - * class or resource itself. The virtual machine's built-in class loader, - * called the "bootstrap class loader", does not itself have a parent but may - * serve as the parent of a <tt>ClassLoader</tt> instance. - * - * <p> Class loaders that support concurrent loading of classes are known as - * <em>parallel capable</em> class loaders and are required to register - * themselves at their class initialization time by invoking the - * {@link - * #registerAsParallelCapable <tt>ClassLoader.registerAsParallelCapable</tt>} - * method. Note that the <tt>ClassLoader</tt> class is registered as parallel - * capable by default. However, its subclasses still need to register themselves - * if they are parallel capable. <br> - * In environments in which the delegation model is not strictly - * hierarchical, class loaders need to be parallel capable, otherwise class - * loading can lead to deadlocks because the loader lock is held for the - * duration of the class loading process (see {@link #loadClass - * <tt>loadClass</tt>} methods). - * - * <p> Normally, the Java virtual machine loads classes from the local file - * system in a platform-dependent manner. For example, on UNIX systems, the - * virtual machine loads classes from the directory defined by the - * <tt>CLASSPATH</tt> environment variable. - * - * <p> However, some classes may not originate from a file; they may originate - * from other sources, such as the network, or they could be constructed by an - * application. The method {@link #defineClass(String, byte[], int, int) - * <tt>defineClass</tt>} converts an array of bytes into an instance of class - * <tt>Class</tt>. Instances of this newly defined class can be created using - * {@link Class#newInstance <tt>Class.newInstance</tt>}. - * - * <p> The methods and constructors of objects created by a class loader may - * reference other classes. To determine the class(es) referred to, the Java - * virtual machine invokes the {@link #loadClass <tt>loadClass</tt>} method of - * the class loader that originally created the class. - * - * <p> For example, an application could create a network class loader to - * download class files from a server. Sample code might look like: - * - * <blockquote><pre> - * ClassLoader loader = new NetworkClassLoader(host, port); - * Object main = loader.loadClass("Main", true).newInstance(); - * . . . - * </pre></blockquote> - * - * <p> The network class loader subclass must define the methods {@link - * #findClass <tt>findClass</tt>} and <tt>loadClassData</tt> to load a class - * from the network. Once it has downloaded the bytes that make up the class, - * it should use the method {@link #defineClass <tt>defineClass</tt>} to - * create a class instance. A sample implementation is: - * - * <blockquote><pre> - * class NetworkClassLoader extends ClassLoader { - * String host; - * int port; - * - * public Class findClass(String name) { - * byte[] b = loadClassData(name); - * return defineClass(name, b, 0, b.length); - * } - * - * private byte[] loadClassData(String name) { - * // load the class data from the connection - * . . . - * } - * } - * </pre></blockquote> - * - * <h4> <a name="name">Binary names</a> </h4> - * - * <p> Any class name provided as a {@link String} parameter to methods in - * <tt>ClassLoader</tt> must be a binary name as defined by - * <cite>The Java™ Language Specification</cite>. - * - * <p> Examples of valid class names include: - * <blockquote><pre> - * "java.lang.String" - * "javax.swing.JSpinner$DefaultEditor" - * "java.security.KeyStore$Builder$FileBuilder$1" - * "java.net.URLClassLoader$3$1" - * </pre></blockquote> - * - * @see #resolveClass(Class) - * @since 1.0 - */ -public abstract class ClassLoader { - - // If initialization succeed this is set to true and security checks will - // succeed. Otherwise the object is not initialized and the object is - // useless. - private final boolean initialized; - - // The parent class loader for delegation - // Note: VM hardcoded the offset of this field, thus all new fields - // must be added *after* it. - private final ClassLoader parent; - - /** - * Encapsulates the set of parallel capable loader types. - */ - private static class ParallelLoaders { - private ParallelLoaders() {} - - // the set of parallel capable loader types - private static final Set<Class<? extends ClassLoader>> loaderTypes = - Collections.newSetFromMap( - new WeakHashMap<Class<? extends ClassLoader>, Boolean>()); - static { - synchronized (loaderTypes) { loaderTypes.add(ClassLoader.class); } - } - - /** - * Registers the given class loader type as parallel capabale. - * Returns {@code true} is successfully registered; {@code false} if - * loader's super class is not registered. - */ - static boolean register(Class<? extends ClassLoader> c) { - synchronized (loaderTypes) { - if (loaderTypes.contains(c.getSuperclass())) { - // register the class loader as parallel capable - // if and only if all of its super classes are. - // Note: given current classloading sequence, if - // the immediate super class is parallel capable, - // all the super classes higher up must be too. - loaderTypes.add(c); - return true; - } else { - return false; - } - } - } - - /** - * Returns {@code true} if the given class loader type is - * registered as parallel capable. - */ - static boolean isRegistered(Class<? extends ClassLoader> c) { - synchronized (loaderTypes) { - return loaderTypes.contains(c); - } - } - } - - // Maps class name to the corresponding lock object when the current - // class loader is parallel capable. - // Note: VM also uses this field to decide if the current class loader - // is parallel capable and the appropriate lock object for class loading. - private final ConcurrentHashMap<String, Object> parallelLockMap; - - // Hashtable that maps packages to certs - private final Map <String, Certificate[]> package2certs; - - // Shared among all packages with unsigned classes - private static final Certificate[] nocerts = new Certificate[0]; - - // The classes loaded by this class loader. The only purpose of this table - // is to keep the classes from being GC'ed until the loader is GC'ed. - private final Vector<Class<?>> classes = new Vector<>(); - - // The "default" domain. Set as the default ProtectionDomain on newly - // created classes. - private final ProtectionDomain defaultDomain = - new ProtectionDomain(new CodeSource(null, (Certificate[]) null), - null, this, null); - - // The initiating protection domains for all classes loaded by this loader - private final Set<ProtectionDomain> domains; - - // Invoked by the VM to record every loaded class with this loader. - void addClass(Class c) { - classes.addElement(c); - } - - // The packages defined in this class loader. Each package name is mapped - // to its corresponding Package object. - // @GuardedBy("itself") - private final HashMap<String, Package> packages = new HashMap<>(); - - @ikvm.lang.Internal - public static final ClassLoader DUMMY = new ClassLoader(false) { }; - - ClassLoader(boolean ignored) - { - // [IKVM] This constructor is IKVM specific and only used to construct DUMMY. - // Note that this body is replaced in map.xml with an empty body as - // we don't want to execute any of the instance field initializers. - this((Void)null, (ClassLoader)null); - } - - private static Void checkCreateClassLoader() { - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkCreateClassLoader(); - } - return null; - } - - // [IKVM] this normally private constructor is also used by ikvm.runtime.AssemblyClassLoader - // to construct an assembly class loader without doing a security check - @ikvm.lang.Internal - protected ClassLoader(Void unused, ClassLoader parent) { - if (parent != null) { - parent.check(); - } - this.parent = parent; - if (ParallelLoaders.isRegistered(this.getClass())) { - parallelLockMap = new ConcurrentHashMap<>(); - package2certs = new ConcurrentHashMap<>(); - domains = - Collections.synchronizedSet(new HashSet<ProtectionDomain>()); - assertionLock = new Object(); - } else { - // no finer-grained lock; lock on the classloader instance - parallelLockMap = null; - package2certs = new Hashtable<>(); - domains = new HashSet<>(); - assertionLock = this; - } - initialized = true; - } - - /** - * Creates a new class loader using the specified parent class loader for - * delegation. - * - * <p> If there is a security manager, its {@link - * SecurityManager#checkCreateClassLoader() - * <tt>checkCreateClassLoader</tt>} method is invoked. This may result in - * a security exception. </p> - * - * @param parent - * The parent class loader - * - * @throws SecurityException - * If a security manager exists and its - * <tt>checkCreateClassLoader</tt> method doesn't allow creation - * of a new class loader. - * - * @since 1.2 - */ - protected ClassLoader(ClassLoader parent) { - this(checkCreateClassLoader(), parent); - } - - /** - * Creates a new class loader using the <tt>ClassLoader</tt> returned by - * the method {@link #getSystemClassLoader() - * <tt>getSystemClassLoader()</tt>} as the parent class loader. - * - * <p> If there is a security manager, its {@link - * SecurityManager#checkCreateClassLoader() - * <tt>checkCreateClassLoader</tt>} method is invoked. This may result in - * a security exception. </p> - * - * @throws SecurityException - * If a security manager exists and its - * <tt>checkCreateClassLoader</tt> method doesn't allow creation - * of a new class loader. - */ - protected ClassLoader() { - this(checkCreateClassLoader(), getSystemClassLoader()); - } - - // -- Class -- - - /** - * Loads the class with the specified <a href="#name">binary name</a>. - * This method searches for classes in the same manner as the {@link - * #loadClass(String, boolean)} method. It is invoked by the Java virtual - * machine to resolve class references. Invoking this method is equivalent - * to invoking {@link #loadClass(String, boolean) <tt>loadClass(name, - * false)</tt>}. </p> - * - * @param name - * The <a href="#name">binary name</a> of the class - * - * @return The resulting <tt>Class</tt> object - * - * @throws ClassNotFoundException - * If the class was not found - */ - public Class<?> loadClass(String name) throws ClassNotFoundException { - return loadClass(name, false); - } - - /** - * Loads the class with the specified <a href="#name">binary name</a>. The - * default implementation of this method searches for classes in the - * following order: - * - * <p><ol> - * - * <li><p> Invoke {@link #findLoadedClass(String)} to check if the class - * has already been loaded. </p></li> - * - * <li><p> Invoke the {@link #loadClass(String) <tt>loadClass</tt>} method - * on the parent class loader. If the parent is <tt>null</tt> the class - * loader built-in to the virtual machine is used, instead. </p></li> - * - * <li><p> Invoke the {@link #findClass(String)} method to find the - * class. </p></li> - * - * </ol> - * - * <p> If the class was found using the above steps, and the - * <tt>resolve</tt> flag is true, this method will then invoke the {@link - * #resolveClass(Class)} method on the resulting <tt>Class</tt> object. - * - * <p> Subclasses of <tt>ClassLoader</tt> are encouraged to override {@link - * #findClass(String)}, rather than this method. </p> - * - * <p> Unless overridden, this method synchronizes on the result of - * {@link #getClassLoadingLock <tt>getClassLoadingLock</tt>} method - * during the entire class loading process. - * - * @param name - * The <a href="#name">binary name</a> of the class - * - * @param resolve - * If <tt>true</tt> then resolve the class - * - * @return The resulting <tt>Class</tt> object - * - * @throws ClassNotFoundException - * If the class could not be found - */ - protected Class<?> loadClass(String name, boolean resolve) - throws ClassNotFoundException - { - synchronized (getClassLoadingLock(name)) { - // First, check if the class has already been loaded - Class c = findLoadedClass(name); - if (c == null) { - try { - if (parent != null) { - c = parent.loadClass(name, false); - } else { - c = findBootstrapClassOrNull(name); - } - } catch (ClassNotFoundException e) { - // ClassNotFoundException thrown if class not found - // from the non-null parent class loader - } - - if (c == null) { - // If still not found, then invoke findClass in order - // to find the class. - c = findClass(name); - } - } - if (resolve) { - resolveClass(c); - } - return c; - } - } - - /** - * Returns the lock object for class loading operations. - * For backward compatibility, the default implementation of this method - * behaves as follows. If this ClassLoader object is registered as - * parallel capable, the method returns a dedicated object associated - * with the specified class name. Otherwise, the method returns this - * ClassLoader object. </p> - * - * @param className - * The name of the to-be-loaded class - * - * @return the lock for class loading operations - * - * @throws NullPointerException - * If registered as parallel capable and <tt>className</tt> is null - * - * @see #loadClass(String, boolean) - * - * @since 1.7 - */ - protected Object getClassLoadingLock(String className) { - Object lock = this; - if (parallelLockMap != null) { - Object newLock = new Object(); - lock = parallelLockMap.putIfAbsent(className, newLock); - if (lock == null) { - lock = newLock; - } - } - return lock; - } - - // This method is invoked by the virtual machine to load a class. - final Class loadClassInternal(String name) - throws ClassNotFoundException - { - // For backward compatibility, explicitly lock on 'this' when - // the current class loader is not parallel capable. - if (parallelLockMap == null) { - synchronized (this) { - return loadClass(name); - } - } else { - return loadClass(name); - } - } - - // Invoked by the VM after loading class with this loader. - final void checkPackageAccess(Class cls, ProtectionDomain pd) { - final SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - final String name = cls.getName(); - final int i = name.lastIndexOf('.'); - if (i != -1) { - AccessController.doPrivileged(new PrivilegedAction<Void>() { - public Void run() { - sm.checkPackageAccess(name.substring(0, i)); - return null; - } - }, new AccessControlContext(new ProtectionDomain[] {pd})); - } - } - domains.add(pd); - } - - /** - * Finds the class with the specified <a href="#name">binary name</a>. - * This method should be overridden by class loader implementations that - * follow the delegation model for loading classes, and will be invoked by - * the {@link #loadClass <tt>loadClass</tt>} method after checking the - * parent class loader for the requested class. The default implementation - * throws a <tt>ClassNotFoundException</tt>. </p> - * - * @param name - * The <a href="#name">binary name</a> of the class - * - * @return The resulting <tt>Class</tt> object - * - * @throws ClassNotFoundException - * If the class could not be found - * - * @since 1.2 - */ - protected Class<?> findClass(String name) throws ClassNotFoundException { - throw new ClassNotFoundException(name); - } - - /** - * Converts an array of bytes into an instance of class <tt>Class</tt>. - * Before the <tt>Class</tt> can be used it must be resolved. This method - * is deprecated in favor of the version that takes a <a - * href="#name">binary name</a> as its first argument, and is more secure. - * - * @param b - * The bytes that make up the class data. The bytes in positions - * <tt>off</tt> through <tt>off+len-1</tt> should have the format - * of a valid class file as defined by - * <cite>The Java™ Virtual Machine Specification</cite>. - * - * @param off - * The start offset in <tt>b</tt> of the class data - * - * @param len - * The length of the class data - * - * @return The <tt>Class</tt> object that was created from the specified - * class data - * - * @throws ClassFormatError - * If the data did not contain a valid class - * - * @throws IndexOutOfBoundsException - * If either <tt>off</tt> or <tt>len</tt> is negative, or if - * <tt>off+len</tt> is greater than <tt>b.length</tt>. - * - * @throws SecurityException - * If an attempt is made to add this class to a package that - * contains classes that were signed by a different set of - * certificates than this class, or if an attempt is made - * to define a class in a package with a fully-qualified name - * that starts with "{@code java.}". - * - * @see #loadClass(String, boolean) - * @see #resolveClass(Class) - * - * @deprecated Replaced by {@link #defineClass(String, byte[], int, int) - * defineClass(String, byte[], int, int)} - */ - @Deprecated - protected final Class<?> defineClass(byte[] b, int off, int len) - throws ClassFormatError - { - return defineClass(null, b, off, len, null); - } - - /** - * Converts an array of bytes into an instance of class <tt>Class</tt>. - * Before the <tt>Class</tt> can be used it must be resolved. - * - * <p> This method assigns a default {@link java.security.ProtectionDomain - * <tt>ProtectionDomain</tt>} to the newly defined class. The - * <tt>ProtectionDomain</tt> is effectively granted the same set of - * permissions returned when {@link - * java.security.Policy#getPermissions(java.security.CodeSource) - * <tt>Policy.getPolicy().getPermissions(new CodeSource(null, null))</tt>} - * is invoked. The default domain is created on the first invocation of - * {@link #defineClass(String, byte[], int, int) <tt>defineClass</tt>}, - * and re-used on subsequent invocations. - * - * <p> To assign a specific <tt>ProtectionDomain</tt> to the class, use - * the {@link #defineClass(String, byte[], int, int, - * java.security.ProtectionDomain) <tt>defineClass</tt>} method that takes a - * <tt>ProtectionDomain</tt> as one of its arguments. </p> - * - * @param name - * The expected <a href="#name">binary name</a> of the class, or - * <tt>null</tt> if not known - * - * @param b - * The bytes that make up the class data. The bytes in positions - * <tt>off</tt> through <tt>off+len-1</tt> should have the format - * of a valid class file as defined by - * <cite>The Java™ Virtual Machine Specification</cite>. - * - * @param off - * The start offset in <tt>b</tt> of the class data - * - * @param len - * The length of the class data - * - * @return The <tt>Class</tt> object that was created from the specified - * class data. - * - * @throws ClassFormatError - * If the data did not contain a valid class - * - * @throws IndexOutOfBoundsException - * If either <tt>off</tt> or <tt>len</tt> is negative, or if - * <tt>off+len</tt> is greater than <tt>b.length</tt>. - * - * @throws SecurityException - * If an attempt is made to add this class to a package that - * contains classes that were signed by a different set of - * certificates than this class (which is unsigned), or if - * <tt>name</tt> begins with "<tt>java.</tt>". - * - * @see #loadClass(String, boolean) - * @see #resolveClass(Class) - * @see java.security.CodeSource - * @see java.security.SecureClassLoader - * - * @since 1.1 - */ - protected final Class<?> defineClass(String name, byte[] b, int off, int len) - throws ClassFormatError - { - return defineClass(name, b, off, len, null); - } - - /* Determine protection domain, and check that: - - not define java.* class, - - signer of this class matches signers for the rest of the classes in - package. - */ - private ProtectionDomain preDefineClass(String name, - ProtectionDomain pd) - { - if (!checkName(name)) - throw new NoClassDefFoundError("IllegalName: " + name); - - if ((name != null) && name.startsWith("java.")) { - throw new SecurityException - ("Prohibited package name: " + - name.substring(0, name.lastIndexOf('.'))); - } - if (pd == null) { - pd = defaultDomain; - } - - if (name != null) checkCerts(name, pd.getCodeSource()); - - return pd; - } - - private String defineClassSourceLocation(ProtectionDomain pd) - { - CodeSource cs = pd.getCodeSource(); - String source = null; - if (cs != null && cs.getLocation() != null) { - source = cs.getLocation().toString(); - } - return source; - } - - private Class defineTransformedClass(String name, byte[] b, int off, int len, - ProtectionDomain pd, - ClassFormatError cfe, String source) - throws ClassFormatError - { - // Class format error - try to transform the bytecode and - // define the class again - // - ClassFileTransformer[] transformers = - ClassFileTransformer.getTransformers(); - Class c = null; - - if (transformers != null) { - for (ClassFileTransformer transformer : transformers) { - try { - // Transform byte code using transformer - byte[] tb = transformer.transform(b, off, len); - c = defineClass1(name, tb, 0, tb.length, - pd, source); - break; - } catch (ClassFormatError cfe2) { - // If ClassFormatError occurs, try next transformer - } - } - } - - // Rethrow original ClassFormatError if unable to transform - // bytecode to well-formed - // - if (c == null) - throw cfe; - - return c; - } - - private void postDefineClass(Class c, ProtectionDomain pd) - { - if (pd.getCodeSource() != null) { - Certificate certs[] = pd.getCodeSource().getCertificates(); - if (certs != null) - setSigners(c, certs); - } - } - - /** - * Converts an array of bytes into an instance of class <tt>Class</tt>, - * with an optional <tt>ProtectionDomain</tt>. If the domain is - * <tt>null</tt>, then a default domain will be assigned to the class as - * specified in the documentation for {@link #defineClass(String, byte[], - * int, int)}. Before the class can be used it must be resolved. - * - * <p> The first class defined in a package determines the exact set of - * certificates that all subsequent classes defined in that package must - * contain. The set of certificates for a class is obtained from the - * {@link java.security.CodeSource <tt>CodeSource</tt>} within the - * <tt>ProtectionDomain</tt> of the class. Any classes added to that - * package must contain the same set of certificates or a - * <tt>SecurityException</tt> will be thrown. Note that if - * <tt>name</tt> is <tt>null</tt>, this check is not performed. - * You should always pass in the <a href="#name">binary name</a> of the - * class you are defining as well as the bytes. This ensures that the - * class you are defining is indeed the class you think it is. - * - * <p> The specified <tt>name</tt> cannot begin with "<tt>java.</tt>", since - * all classes in the "<tt>java.*</tt> packages can only be defined by the - * bootstrap class loader. If <tt>name</tt> is not <tt>null</tt>, it - * must be equal to the <a href="#name">binary name</a> of the class - * specified by the byte array "<tt>b</tt>", otherwise a {@link - * <tt>NoClassDefFoundError</tt>} will be thrown. </p> - * - * @param name - * The expected <a href="#name">binary name</a> of the class, or - * <tt>null</tt> if not known - * - * @param b - * The bytes that make up the class data. The bytes in positions - * <tt>off</tt> through <tt>off+len-1</tt> should have the format - * of a valid class file as defined by - * <cite>The Java™ Virtual Machine Specification</cite>. - * - * @param off - * The start offset in <tt>b</tt> of the class data - * - * @param len - * The length of the class data - * - * @param protectionDomain - * The ProtectionDomain of the class - * - * @return The <tt>Class</tt> object created from the data, - * and optional <tt>ProtectionDomain</tt>. - * - * @throws ClassFormatError - * If the data did not contain a valid class - * - * @throws NoClassDefFoundError - * If <tt>name</tt> is not equal to the <a href="#name">binary - * name</a> of the class specified by <tt>b</tt> - * - * @throws IndexOutOfBoundsException - * If either <tt>off</tt> or <tt>len</tt> is negative, or if - * <tt>off+len</tt> is greater than <tt>b.length</tt>. - * - * @throws SecurityException - * If an attempt is made to add this class to a package that - * contains classes that were signed by a different set of - * certificates than this class, or if <tt>name</tt> begins with - * "<tt>java.</tt>". - */ - protected final Class<?> defineClass(String name, byte[] b, int off, int len, - ProtectionDomain protectionDomain) - throws ClassFormatError - { - check(); - protectionDomain = preDefineClass(name, protectionDomain); - - Class c = null; - String source = defineClassSourceLocation(protectionDomain); - - try { - c = defineClass1(name, b, off, len, protectionDomain, source); - } catch (ClassFormatError cfe) { - c = defineTransformedClass(name, b, off, len, protectionDomain, cfe, - source); - } - - postDefineClass(c, protectionDomain); - return c; - } - - /** - * Converts a {@link java.nio.ByteBuffer <tt>ByteBuffer</tt>} - * into an instance of class <tt>Class</tt>, - * with an optional <tt>ProtectionDomain</tt>. If the domain is - * <tt>null</tt>, then a default domain will be assigned to the class as - * specified in the documentation for {@link #defineClass(String, byte[], - * int, int)}. Before the class can be used it must be resolved. - * - * <p>The rules about the first class defined in a package determining the - * set of certificates for the package, and the restrictions on class names - * are identical to those specified in the documentation for {@link - * #defineClass(String, byte[], int, int, ProtectionDomain)}. - * - * <p> An invocation of this method of the form - * <i>cl</i><tt>.defineClass(</tt><i>name</i><tt>,</tt> - * <i>bBuffer</i><tt>,</tt> <i>pd</i><tt>)</tt> yields exactly the same - * result as the statements - * - * <blockquote><tt> - * ...<br> - * byte[] temp = new byte[</tt><i>bBuffer</i><tt>.{@link - * java.nio.ByteBuffer#remaining remaining}()];<br> - * </tt><i>bBuffer</i><tt>.{@link java.nio.ByteBuffer#get(byte[]) - * get}(temp);<br> - * return {@link #defineClass(String, byte[], int, int, ProtectionDomain) - * </tt><i>cl</i><tt>.defineClass}(</tt><i>name</i><tt>, temp, 0, - * temp.length, </tt><i>pd</i><tt>);<br> - * </tt></blockquote> - * - * @param name - * The expected <a href="#name">binary name</a>. of the class, or - * <tt>null</tt> if not known - * - * @param b - * The bytes that make up the class data. The bytes from positions - * <tt>b.position()</tt> through <tt>b.position() + b.limit() -1 - * </tt> should have the format of a valid class file as defined by - * <cite>The Java™ Virtual Machine Specification</cite>. - * - * @param protectionDomain - * The ProtectionDomain of the class, or <tt>null</tt>. - * - * @return The <tt>Class</tt> object created from the data, - * and optional <tt>ProtectionDomain</tt>. - * - * @throws ClassFormatError - * If the data did not contain a valid class. - * - * @throws NoClassDefFoundError - * If <tt>name</tt> is not equal to the <a href="#name">binary - * name</a> of the class specified by <tt>b</tt> - * - * @throws SecurityException - * If an attempt is made to add this class to a package that - * contains classes that were signed by a different set of - * certificates than this class, or if <tt>name</tt> begins with - * "<tt>java.</tt>". - * - * @see #defineClass(String, byte[], int, int, ProtectionDomain) - * - * @since 1.5 - */ - protected final Class<?> defineClass(String name, java.nio.ByteBuffer b, - ProtectionDomain protectionDomain) - throws ClassFormatError - { - check(); - - int len = b.remaining(); - - // Use byte[] if not a direct ByteBufer: - if (!b.isDirect()) { - if (b.hasArray()) { - return defineClass(name, b.array(), - b.position() + b.arrayOffset(), len, - protectionDomain); - } else { - // no array, or read-only array - byte[] tb = new byte[len]; - b.get(tb); // get bytes out of byte buffer. - return defineClass(name, tb, 0, len, protectionDomain); - } - } - - protectionDomain = preDefineClass(name, protectionDomain); - - Class c = null; - String source = defineClassSourceLocation(protectionDomain); - - try { - c = defineClass2(name, b, b.position(), len, protectionDomain, - source); - } catch (ClassFormatError cfe) { - byte[] tb = new byte[len]; - b.get(tb); // get bytes out of byte buffer. - c = defineTransformedClass(name, tb, 0, len, protectionDomain, cfe, - source); - } - - postDefineClass(c, protectionDomain); - return c; - } - - private native Class defineClass0(String name, byte[] b, int off, int len, - ProtectionDomain pd); - - private native Class defineClass1(String name, byte[] b, int off, int len, - ProtectionDomain pd, String source); - - private native Class defineClass2(String name, java.nio.ByteBuffer b, - int off, int len, ProtectionDomain pd, - String source); - - // true if the name is null or has the potential to be a valid binary name - static boolean checkName(String name) { - if ((name == null) || (name.length() == 0)) - return true; - if ((name.indexOf('/') != -1) - || (!VM.allowArraySyntax() && (name.charAt(0) == '['))) - return false; - return true; - } - - private void checkCerts(String name, CodeSource cs) { - int i = name.lastIndexOf('.'); - String pname = (i == -1) ? "" : name.substring(0, i); - - Certificate[] certs = null; - if (cs != null) { - certs = cs.getCertificates(); - } - Certificate[] pcerts = null; - if (parallelLockMap == null) { - synchronized (this) { - pcerts = package2certs.get(pname); - if (pcerts == null) { - package2certs.put(pname, (certs == null? nocerts:certs)); - } - } - } else { - pcerts = ((ConcurrentHashMap<String, Certificate[]>)package2certs). - putIfAbsent(pname, (certs == null? nocerts:certs)); - } - if (pcerts != null && !compareCerts(pcerts, certs)) { - throw new SecurityException("class \""+ name + - "\"'s signer information does not match signer information of other classes in the same package"); - } - } - - /** - * check to make sure the certs for the new class (certs) are the same as - * the certs for the first class inserted in the package (pcerts) - */ - private boolean compareCerts(Certificate[] pcerts, - Certificate[] certs) - { - // certs can be null, indicating no certs. - if ((certs == null) || (certs.length == 0)) { - return pcerts.length == 0; - } - - // the length must be the same at this point - if (certs.length != pcerts.length) - return false; - - // go through and make sure all the certs in one array - // are in the other and vice-versa. - boolean match; - for (int i = 0; i < certs.length; i++) { - match = false; - for (int j = 0; j < pcerts.length; j++) { - if (certs[i].equals(pcerts[j])) { - match = true; - break; - } - } - if (!match) return false; - } - - // now do the same for pcerts - for (int i = 0; i < pcerts.length; i++) { - match = false; - for (int j = 0; j < certs.length; j++) { - if (pcerts[i].equals(certs[j])) { - match = true; - break; - } - } - if (!match) return false; - } - - return true; - } - - /** - * Links the specified class. This (misleadingly named) method may be - * used by a class loader to link a class. If the class <tt>c</tt> has - * already been linked, then this method simply returns. Otherwise, the - * class is linked as described in the "Execution" chapter of - * <cite>The Java™ Language Specification</cite>. - * </p> - * - * @param c - * The class to link - * - * @throws NullPointerException - * If <tt>c</tt> is <tt>null</tt>. - * - * @see #defineClass(String, byte[], int, int) - */ - protected final void resolveClass(Class<?> c) { - check(); - resolveClass0(c); - } - - private native void resolveClass0(Class c); - - /** - * Finds a class with the specified <a href="#name">binary name</a>, - * loading it if necessary. - * - * <p> This method loads the class through the system class loader (see - * {@link #getSystemClassLoader()}). The <tt>Class</tt> object returned - * might have more than one <tt>ClassLoader</tt> associated with it. - * Subclasses of <tt>ClassLoader</tt> need not usually invoke this method, - * because most class loaders need to override just {@link - * #findClass(String)}. </p> - * - * @param name - * The <a href="#name">binary name</a> of the class - * - * @return The <tt>Class</tt> object for the specified <tt>name</tt> - * - * @throws ClassNotFoundException - * If the class could not be found - * - * @see #ClassLoader(ClassLoader) - * @see #getParent() - */ - protected final Class<?> findSystemClass(String name) - throws ClassNotFoundException - { - check(); - ClassLoader system = getSystemClassLoader(); - if (system == null) { - if (!checkName(name)) - throw new ClassNotFoundException(name); - Class cls = findBootstrapClass(name); - if (cls == null) { - throw new ClassNotFoundException(name); - } - return cls; - } - return system.loadClass(name); - } - - /** - * Returns a class loaded by the bootstrap class loader; - * or return null if not found. - */ - private Class findBootstrapClassOrNull(String name) - { - check(); - if (!checkName(name)) return null; - - return findBootstrapClass(name); - } - - // return null if not found - private native Class findBootstrapClass(String name); - - // Check to make sure the class loader has been initialized. - private void check() { - if (!initialized) { - throw new SecurityException("ClassLoader object not initialized"); - } - } - - /** - * Returns the class with the given <a href="#name">binary name</a> if this - * loader has been recorded by the Java virtual machine as an initiating - * loader of a class with that <a href="#name">binary name</a>. Otherwise - * <tt>null</tt> is returned. </p> - * - * @param name - * The <a href="#name">binary name</a> of the class - * - * @return The <tt>Class</tt> object, or <tt>null</tt> if the class has - * not been loaded - * - * @since 1.1 - */ - protected final Class<?> findLoadedClass(String name) { - check(); - if (!checkName(name)) - return null; - return findLoadedClass0(name); - } - - private native final Class findLoadedClass0(String name); - - /** - * Sets the signers of a class. This should be invoked after defining a - * class. </p> - * - * @param c - * The <tt>Class</tt> object - * - * @param signers - * The signers for the class - * - * @since 1.1 - */ - protected final void setSigners(Class<?> c, Object[] signers) { - check(); - c.setSigners(signers); - } - - - // -- Resource -- - - /** - * Finds the resource with the given name. A resource is some data - * (images, audio, text, etc) that can be accessed by class code in a way - * that is independent of the location of the code. - * - * <p> The name of a resource is a '<tt>/</tt>'-separated path name that - * identifies the resource. - * - * <p> This method will first search the parent class loader for the - * resource; if the parent is <tt>null</tt> the path of the class loader - * built-in to the virtual machine is searched. That failing, this method - * will invoke {@link #findResource(String)} to find the resource. </p> - * - * @param name - * The resource name - * - * @return A <tt>URL</tt> object for reading the resource, or - * <tt>null</tt> if the resource could not be found or the invoker - * doesn't have adequate privileges to get the resource. - * - * @since 1.1 - */ - public URL getResource(String name) { - URL url; - if (parent != null) { - url = parent.getResource(name); - } else { - url = getBootstrapResource(name); - } - if (url == null) { - url = findResource(name); - } - return url; - } - - /** - * Finds all the resources with the given name. A resource is some data - * (images, audio, text, etc) that can be accessed by class code in a way - * that is independent of the location of the code. - * - * <p>The name of a resource is a <tt>/</tt>-separated path name that - * identifies the resource. - * - * <p> The search order is described in the documentation for {@link - * #getResource(String)}. </p> - * - * @param name - * The resource name - * - * @return An enumeration of {@link java.net.URL <tt>URL</tt>} objects for - * the resource. If no resources could be found, the enumeration - * will be empty. Resources that the class loader doesn't have - * access to will not be in the enumeration. - * - * @throws IOException - * If I/O errors occur - * - * @see #findResources(String) - * - * @since 1.2 - */ - public Enumeration<URL> getResources(String name) throws IOException { - Enumeration[] tmp = new Enumeration[2]; - if (parent != null) { - tmp[0] = parent.getResources(name); - } else { - tmp[0] = getBootstrapResources(name); - } - tmp[1] = findResources(name); - - return new CompoundEnumeration<>(tmp); - } - - /** - * Finds the resource with the given name. Class loader implementations - * should override this method to specify where to find resources. </p> - * - * @param name - * The resource name - * - * @return A <tt>URL</tt> object for reading the resource, or - * <tt>null</tt> if the resource could not be found - * - * @since 1.2 - */ - protected URL findResource(String name) { - return null; - } - - /** - * Returns an enumeration of {@link java.net.URL <tt>URL</tt>} objects - * representing all the resources with the given name. Class loader - * implementations should override this method to specify where to load - * resources from. </p> - * - * @param name - * The resource name - * - * @return An enumeration of {@link java.net.URL <tt>URL</tt>} objects for - * the resources - * - * @throws IOException - * If I/O errors occur - * - * @since 1.2 - */ - protected Enumeration<URL> findResources(String name) throws IOException { - return java.util.Collections.emptyEnumeration(); - } - - /** - * Registers the caller as parallel capable.</p> - * The registration succeeds if and only if all of the following - * conditions are met: <br> - * 1. no instance of the caller has been created</p> - * 2. all of the super classes (except class Object) of the caller are - * registered as parallel capable</p> - * Note that once a class loader is registered as parallel capable, there - * is no way to change it back. </p> - * - * @return true if the caller is successfully registered as - * parallel capable and false if otherwise. - * - * @since 1.7 - */ - @CallerSensitive - protected static boolean registerAsParallelCapable() { - Class<? extends ClassLoader> callerClass = - Reflection.getCallerClass().asSubclass(ClassLoader.class); - return ParallelLoaders.register(callerClass); - } - - /** - * Find a resource of the specified name from the search path used to load - * classes. This method locates the resource through the system class - * loader (see {@link #getSystemClassLoader()}). </p> - * - * @param name - * The resource name - * - * @return A {@link java.net.URL <tt>URL</tt>} object for reading the - * resource, or <tt>null</tt> if the resource could not be found - * - * @since 1.1 - */ - public static URL getSystemResource(String name) { - ClassLoader system = getSystemClassLoader(); - if (system == null) { - return getBootstrapResource(name); - } - return system.getResource(name); - } - - /** - * Finds all resources of the specified name from the search path used to - * load classes. The resources thus found are returned as an - * {@link java.util.Enumeration <tt>Enumeration</tt>} of {@link - * java.net.URL <tt>URL</tt>} objects. - * - * <p> The search order is described in the documentation for {@link - * #getSystemResource(String)}. </p> - * - * @param name - * The resource name - * - * @return An enumeration of resource {@link java.net.URL <tt>URL</tt>} - * objects - * - * @throws IOException - * If I/O errors occur - - * @since 1.2 - */ - public static Enumeration<URL> getSystemResources(String name) - throws IOException - { - ClassLoader system = getSystemClassLoader(); - if (system == null) { - return getBootstrapResources(name); - } - return system.getResources(name); - } - - /** - * Find resources from the VM's built-in classloader. - */ - private static native URL getBootstrapResource(String name); - - /** - * Find resources from the VM's built-in classloader. - */ - private static native Enumeration<URL> getBootstrapResources(String name) - throws IOException; - - // Returns the URLClassPath that is used for finding system resources. - static URLClassPath getBootstrapClassPath() { - return sun.misc.Launcher.getBootstrapClassPath(); - } - - - /** - * Returns an input stream for reading the specified resource. - * - * <p> The search order is described in the documentation for {@link - * #getResource(String)}. </p> - * - * @param name - * The resource name - * - * @return An input stream for reading the resource, or <tt>null</tt> - * if the resource could not be found - * - * @since 1.1 - */ - public InputStream getResourceAsStream(String name) { - URL url = getResource(name); - try { - return url != null ? url.openStream() : null; - } catch (IOException e) { - return null; - } - } - - /** - * Open for reading, a resource of the specified name from the search path - * used to load classes. This method locates the resource through the - * system class loader (see {@link #getSystemClassLoader()}). </p> - * - * @param name - * The resource name - * - * @return An input stream for reading the resource, or <tt>null</tt> - * if the resource could not be found - * - * @since 1.1 - */ - public static InputStream getSystemResourceAsStream(String name) { - URL url = getSystemResource(name); - try { - return url != null ? url.openStream() : null; - } catch (IOException e) { - return null; - } - } - - - // -- Hierarchy -- - - /** - * Returns the parent class loader for delegation. Some implementations may - * use <tt>null</tt> to represent the bootstrap class loader. This method - * will return <tt>null</tt> in such implementations if this class loader's - * parent is the bootstrap class loader. - * - * <p> If a security manager is present, and the invoker's class loader is - * not <tt>null</tt> and is not an ancestor of this class loader, then this - * method invokes the security manager's {@link - * SecurityManager#checkPermission(java.security.Permission) - * <tt>checkPermission</tt>} method with a {@link - * RuntimePermission#RuntimePermission(String) - * <tt>RuntimePermission("getClassLoader")</tt>} permission to verify - * access to the parent class loader is permitted. If not, a - * <tt>SecurityException</tt> will be thrown. </p> - * - * @return The parent <tt>ClassLoader</tt> - * - * @throws SecurityException - * If a security manager exists and its <tt>checkPermission</tt> - * method doesn't allow access to this class loader's parent class - * loader. - * - * @since 1.2 - */ - @CallerSensitive - public final ClassLoader getParent() { - if (parent == null) - return null; - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkClassLoaderPermission(parent, Reflection.getCallerClass()); - } - return parent; - } - - /** - * Returns the system class loader for delegation. This is the default - * delegation parent for new <tt>ClassLoader</tt> instances, and is - * typically the class loader used to start the application. - * - * <p> This method is first invoked early in the runtime's startup - * sequence, at which point it creates the system class loader and sets it - * as the context class loader of the invoking <tt>Thread</tt>. - * - * <p> The default system class loader is an implementation-dependent - * instance of this class. - * - * <p> If the system property "<tt>java.system.class.loader</tt>" is defined - * when this method is first invoked then the value of that property is - * taken to be the name of a class that will be returned as the system - * class loader. The class is loaded using the default system class loader - * and must define a public constructor that takes a single parameter of - * type <tt>ClassLoader</tt> which is used as the delegation parent. An - * instance is then created using this constructor with the default system - * class loader as the parameter. The resulting class loader is defined - * to be the system class loader. - * - * <p> If a security manager is present, and the invoker's class loader is - * not <tt>null</tt> and the invoker's class loader is not the same as or - * an ancestor of the system class loader, then this method invokes the - * security manager's {@link - * SecurityManager#checkPermission(java.security.Permission) - * <tt>checkPermission</tt>} method with a {@link - * RuntimePermission#RuntimePermission(String) - * <tt>RuntimePermission("getClassLoader")</tt>} permission to verify - * access to the system class loader. If not, a - * <tt>SecurityException</tt> will be thrown. </p> - * - * @return The system <tt>ClassLoader</tt> for delegation, or - * <tt>null</tt> if none - * - * @throws SecurityException - * If a security manager exists and its <tt>checkPermission</tt> - * method doesn't allow access to the system class loader. - * - * @throws IllegalStateException - * If invoked recursively during the construction of the class - * loader specified by the "<tt>java.system.class.loader</tt>" - * property. - * - * @throws Error - * If the system property "<tt>java.system.class.loader</tt>" - * is defined but the named class could not be loaded, the - * provider class does not define the required constructor, or an - * exception is thrown by that constructor when it is invoked. The - * underlying cause of the error can be retrieved via the - * {@link Throwable#getCause()} method. - * - * @revised 1.4 - */ - @CallerSensitive - public static ClassLoader getSystemClassLoader() { - initSystemClassLoader(); - if (scl == null) { - return null; - } - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkClassLoaderPermission(scl, Reflection.getCallerClass()); - } - return scl; - } - - private static synchronized void initSystemClassLoader() { - if (!sclSet) { - if (scl != null) - throw new IllegalStateException("recursive invocation"); - sun.misc.Launcher l = sun.misc.Launcher.getLauncher(); - if (l != null) { - Throwable oops = null; - scl = l.getClassLoader(); - try { - scl = AccessController.doPrivileged( - new SystemClassLoaderAction(scl)); - } catch (PrivilegedActionException pae) { - oops = pae.getCause(); - if (oops instanceof InvocationTargetException) { - oops = oops.getCause(); - } - } - if (oops != null) { - if (oops instanceof Error) { - throw (Error) oops; - } else { - // wrap the exception - throw new Error(oops); - } - } - } - sclSet = true; - } - } - - // Returns true if the specified class loader can be found in this class - // loader's delegation chain. - boolean isAncestor(ClassLoader cl) { - ClassLoader acl = this; - do { - acl = acl.parent; - if (cl == acl) { - return true; - } - } while (acl != null); - return false; - } - - // Tests if class loader access requires "getClassLoader" permission - // check. A class loader 'from' can access class loader 'to' if - // class loader 'from' is same as class loader 'to' or an ancestor - // of 'to'. The class loader in a system domain can access - // any class loader. - private static boolean needsClassLoaderPermissionCheck(ClassLoader from, - ClassLoader to) - { - if (from == to) - return false; - - if (from == null) - return false; - - return !to.isAncestor(from); - } - - // Returns the class's class loader, or null if none. - static ClassLoader getClassLoader(Class<?> caller) { - // This can be null if the VM is requesting it - if (caller == null) { - return null; - } - // Circumvent security check since this is package-private - return caller.getClassLoader0(); - } - - static void checkClassLoaderPermission(ClassLoader cl, Class<?> caller) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - // caller can be null if the VM is requesting it - ClassLoader ccl = getClassLoader(caller); - if (needsClassLoaderPermissionCheck(ccl, cl)) { - sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); - } - } - } - - // The class loader for the system - // @GuardedBy("ClassLoader.class") - private static ClassLoader scl; - - // Set to true once the system class loader has been set - // @GuardedBy("ClassLoader.class") - private static boolean sclSet; - - - // -- Package -- - - /** - * Defines a package by name in this <tt>ClassLoader</tt>. This allows - * class loaders to define the packages for their classes. Packages must - * be created before the class is defined, and package names must be - * unique within a class loader and cannot be redefined or changed once - * created. </p> - * - * @param name - * The package name - * - * @param specTitle - * The specification title - * - * @param specVersion - * The specification version - * - * @param specVendor - * The specification vendor - * - * @param implTitle - * The implementation title - * - * @param implVersion - * The implementation version - * - * @param implVendor - * The implementation vendor - * - * @param sealBase - * If not <tt>null</tt>, then this package is sealed with - * respect to the given code source {@link java.net.URL - * <tt>URL</tt>} object. Otherwise, the package is not sealed. - * - * @return The newly defined <tt>Package</tt> object - * - * @throws IllegalArgumentException - * If package name duplicates an existing package either in this - * class loader or one of its ancestors - * - * @since 1.2 - */ - protected Package definePackage(String name, String specTitle, - String specVersion, String specVendor, - String implTitle, String implVersion, - String implVendor, URL sealBase) - throws IllegalArgumentException - { - synchronized (packages) { - Package pkg = getPackage(name); - if (pkg != null) { - throw new IllegalArgumentException(name); - } - pkg = new Package(name, specTitle, specVersion, specVendor, - implTitle, implVersion, implVendor, - sealBase, this); - packages.put(name, pkg); - return pkg; - } - } - - /** - * Returns a <tt>Package</tt> that has been defined by this class loader - * or any of its ancestors. </p> - * - * @param name - * The package name - * - * @return The <tt>Package</tt> corresponding to the given name, or - * <tt>null</tt> if not found - * - * @since 1.2 - */ - protected Package getPackage(String name) { - Package pkg; - synchronized (packages) { - pkg = packages.get(name); - } - if (pkg == null) { - if (parent != null) { - pkg = parent.getPackage(name); - } else { - pkg = Package.getSystemPackage(name); - } - if (pkg != null) { - synchronized (packages) { - Package pkg2 = packages.get(name); - if (pkg2 == null) { - packages.put(name, pkg); - } else { - pkg = pkg2; - } - } - } - } - return pkg; - } - - /** - * Returns all of the <tt>Packages</tt> defined by this class loader and - * its ancestors. </p> - * - * @return The array of <tt>Package</tt> objects defined by this - * <tt>ClassLoader</tt> - * - * @since 1.2 - */ - protected Package[] getPackages() { - Map<String, Package> map; - synchronized (packages) { - map = new HashMap<>(packages); - } - Package[] pkgs; - if (parent != null) { - pkgs = parent.getPackages(); - } else { - pkgs = Package.getSystemPackages(); - } - if (pkgs != null) { - for (int i = 0; i < pkgs.length; i++) { - String pkgName = pkgs[i].getName(); - if (map.get(pkgName) == null) { - map.put(pkgName, pkgs[i]); - } - } - } - return map.values().toArray(new Package[map.size()]); - } - - - // -- Native library access -- - - /** - * Returns the absolute path name of a native library. The VM invokes this - * method to locate the native libraries that belong to classes loaded with - * this class loader. If this method returns <tt>null</tt>, the VM - * searches the library along the path specified as the - * "<tt>java.library.path</tt>" property. </p> - * - * @param libname - * The library name - * - * @return The absolute path of the native library - * - * @see System#loadLibrary(String) - * @see System#mapLibraryName(String) - * - * @since 1.2 - */ - protected String findLibrary(String libname) { - return null; - } - - /** - * The inner class NativeLibrary denotes a loaded native library instance. - * Every classloader contains a vector of loaded native libraries in the - * private field <tt>nativeLibraries</tt>. The native libraries loaded - * into the system are entered into the <tt>systemNativeLibraries</tt> - * vector. - * - * <p> Every native library requires a particular version of JNI. This is - * denoted by the private <tt>jniVersion</tt> field. This field is set by - * the VM when it loads the library, and used by the VM to pass the correct - * version of JNI to the native methods. </p> - * - * @see ClassLoader - * @since 1.2 - */ - static class NativeLibrary { - // opaque handle to native library, used in native code. - long handle; - // the version of JNI environment the native library requires. - private int jniVersion; - // the class from which the library is loaded, also indicates - // the loader this native library belongs. - Class fromClass; - // the canonicalized name of the native library. - String name; - - native void load(String name); - native long find(String name); - native void unload(); - - public NativeLibrary(Class fromClass, String name) { - this.name = name; - this.fromClass = fromClass; - } - - protected void finalize() { - synchronized (loadedLibraryNames) { - if (fromClass.getClassLoader() != null && handle != 0) { - /* remove the native library name */ - int size = loadedLibraryNames.size(); - for (int i = 0; i < size; i++) { - if (name.equals(loadedLibraryNames.elementAt(i))) { - loadedLibraryNames.removeElementAt(i); - break; - } - } - /* unload the library. */ - ClassLoader.nativeLibraryContext.push(this); - try { - unload(); - } finally { - ClassLoader.nativeLibraryContext.pop(); - } - } - } - } - // Invoked in the VM to determine the context class in - // JNI_Load/JNI_Unload - static Class getFromClass() { - return ClassLoader.nativeLibraryContext.peek().fromClass; - } - } - - // All native library names we've loaded. - private static Vector<String> loadedLibraryNames = new Vector<>(); - - // Native libraries belonging to system classes. - private static Vector<NativeLibrary> systemNativeLibraries - = new Vector<>(); - - // Native libraries associated with the class loader. - private Vector<NativeLibrary> nativeLibraries = new Vector<>(); - - // native libraries being loaded/unloaded. - private static Stack<NativeLibrary> nativeLibraryContext = new Stack<>(); - - // The paths searched for libraries - private static String usr_paths[]; - private static String sys_paths[]; - - private static String[] initializePath(String ldpath) { - String ps = File.pathSeparator; - int ldlen = ldpath.length(); - int i, j, n; - // Count the separators in the path - i = ldpath.indexOf(ps); - n = 0; - while (i >= 0) { - n++; - i = ldpath.indexOf(ps, i + 1); - } - - // allocate the array of paths - n :'s = n + 1 path elements - String[] paths = new String[n + 1]; - - // Fill the array with paths from the ldpath - n = i = 0; - j = ldpath.indexOf(ps); - while (j >= 0) { - if (j - i > 0) { - paths[n++] = ldpath.substring(i, j); - } else if (j - i == 0) { - paths[n++] = "."; - } - i = j + 1; - j = ldpath.indexOf(ps, i); - } - paths[n] = ldpath.substring(i, ldlen); - return paths; - } - - private static String java_library_path; - private static String sun_boot_library_path; - - static void initializeLibraryPaths(java.util.Properties props) - { - java_library_path = props.getProperty("java.library.path", ""); - sun_boot_library_path = props.getProperty("sun.boot.library.path", ""); - } - - // Invoked in the java.lang.Runtime class to implement load and loadLibrary. - static void loadLibrary(Class fromClass, String name, - boolean isAbsolute) { - ClassLoader loader = - (fromClass == null) ? null : fromClass.getClassLoader(); - if (sys_paths == null) { - usr_paths = initializePath(java_library_path); - sys_paths = initializePath(sun_boot_library_path); - } - if (isAbsolute) { - if (loadLibrary0(fromClass, new File(name))) { - return; - } - throw new UnsatisfiedLinkError("Can't load library: " + name); - } - if (loader != null) { - String libfilename = loader.findLibrary(name); - if (libfilename != null) { - File libfile = new File(libfilename); - if (!libfile.isAbsolute()) { - throw new UnsatisfiedLinkError( - "ClassLoader.findLibrary failed to return an absolute path: " + libfilename); - } - if (loadLibrary0(fromClass, libfile)) { - return; - } - throw new UnsatisfiedLinkError("Can't load " + libfilename); - } - } - for (int i = 0 ; i < sys_paths.length ; i++) { - File libfile = new File(sys_paths[i], System.mapLibraryName(name)); - if (loadLibrary0(fromClass, libfile)) { - return; - } - } - if (loader != null) { - for (int i = 0 ; i < usr_paths.length ; i++) { - File libfile = new File(usr_paths[i], - System.mapLibraryName(name)); - if (loadLibrary0(fromClass, libfile)) { - return; - } - } - } - // Oops, it failed - throw new UnsatisfiedLinkError("no " + name + " in java.library.path"); - } - - private static boolean loadLibrary0(Class fromClass, final File file) { - if (loadLibrary1(fromClass, file)) { - return true; - } - final File libfile = ClassLoaderHelper.mapAlternativeName(file); - if (libfile != null && loadLibrary1(fromClass, libfile)) { - return true; - } - return false; - } - - private static boolean loadLibrary1(Class fromClass, final File file) { - boolean exists = AccessController.doPrivileged( - new PrivilegedAction<Object>() { - public Object run() { - return file.exists() ? Boolean.TRUE : null; - }}) - != null; - if (!exists) { - return false; - } - String name; - try { - name = file.getCanonicalPath(); - } catch (IOException e) { - return false; - } - ClassLoader loader = - (fromClass == null) ? null : fromClass.getClassLoader(); - Vector<NativeLibrary> libs = - loader != null ? loader.nativeLibraries : systemNativeLibraries; - synchronized (libs) { - int size = libs.size(); - for (int i = 0; i < size; i++) { - NativeLibrary lib = libs.elementAt(i); - if (name.equals(lib.name)) { - return true; - } - } - - synchronized (loadedLibraryNames) { - if (loadedLibraryNames.contains(name)) { - throw new UnsatisfiedLinkError - ("Native Library " + - name + - " already loaded in another classloader"); - } - /* If the library is being loaded (must be by the same thread, - * because Runtime.load and Runtime.loadLibrary are - * synchronous). The reason is can occur is that the JNI_OnLoad - * function can cause another loadLibrary invocation. - * - * Thus we can use a static stack to hold the list of libraries - * we are loading. - * - * If there is a pending load operation for the library, we - * immediately return success; otherwise, we raise - * UnsatisfiedLinkError. - */ - int n = nativeLibraryContext.size(); - for (int i = 0; i < n; i++) { - NativeLibrary lib = nativeLibraryContext.elementAt(i); - if (name.equals(lib.name)) { - if (loader == lib.fromClass.getClassLoader()) { - return true; - } else { - throw new UnsatisfiedLinkError - ("Native Library " + - name + - " is being loaded in another classloader"); - } - } - } - NativeLibrary lib = new NativeLibrary(fromClass, name); - nativeLibraryContext.push(lib); - try { - lib.load(name); - } finally { - nativeLibraryContext.pop(); - } - if (lib.handle != 0) { - loadedLibraryNames.addElement(name); - libs.addElement(lib); - return true; - } - return false; - } - } - } - - // Invoked in the VM class linking code. - static long findNative(ClassLoader loader, String name) { - Vector<NativeLibrary> libs = - loader != null ? loader.nativeLibraries : systemNativeLibraries; - synchronized (libs) { - int size = libs.size(); - for (int i = 0; i < size; i++) { - NativeLibrary lib = libs.elementAt(i); - long entry = lib.find(name); - if (entry != 0) - return entry; - } - } - return 0; - } - - - // -- Assertion management -- - - final Object assertionLock; - - // The default toggle for assertion checking. - // @GuardedBy("assertionLock") - private boolean defaultAssertionStatus = false; - - // Maps String packageName to Boolean package default assertion status Note - // that the default package is placed under a null map key. If this field - // is null then we are delegating assertion status queries to the VM, i.e., - // none of this ClassLoader's assertion status modification methods have - // been invoked. - // @GuardedBy("assertionLock") - private Map<String, Boolean> packageAssertionStatus = null; - - // Maps String fullyQualifiedClassName to Boolean assertionStatus If this - // field is null then we are delegating assertion status queries to the VM, - // i.e., none of this ClassLoader's assertion status modification methods - // have been invoked. - // @GuardedBy("assertionLock") - Map<String, Boolean> classAssertionStatus = null; - - /** - * Sets the default assertion status for this class loader. This setting - * determines whether classes loaded by this class loader and initialized - * in the future will have assertions enabled or disabled by default. - * This setting may be overridden on a per-package or per-class basis by - * invoking {@link #setPackageAssertionStatus(String, boolean)} or {@link - * #setClassAssertionStatus(String, boolean)}. </p> - * - * @param enabled - * <tt>true</tt> if classes loaded by this class loader will - * henceforth have assertions enabled by default, <tt>false</tt> - * if they will have assertions disabled by default. - * - * @since 1.4 - */ - public void setDefaultAssertionStatus(boolean enabled) { - synchronized (assertionLock) { - if (classAssertionStatus == null) - initializeJavaAssertionMaps(); - - defaultAssertionStatus = enabled; - } - } - - /** - * Sets the package default assertion status for the named package. The - * package default assertion status determines the assertion status for - * classes initialized in the future that belong to the named package or - * any of its "subpackages". - * - * <p> A subpackage of a package named p is any package whose name begins - * with "<tt>p.</tt>". For example, <tt>javax.swing.text</tt> is a - * subpackage of <tt>javax.swing</tt>, and both <tt>java.util</tt> and - * <tt>java.lang.reflect</tt> are subpackages of <tt>java</tt>. - * - * <p> In the event that multiple package defaults apply to a given class, - * the package default pertaining to the most specific package takes - * precedence over the others. For example, if <tt>javax.lang</tt> and - * <tt>javax.lang.reflect</tt> both have package defaults associated with - * them, the latter package default applies to classes in - * <tt>javax.lang.reflect</tt>. - * - * <p> Package defaults take precedence over the class loader's default - * assertion status, and may be overridden on a per-class basis by invoking - * {@link #setClassAssertionStatus(String, boolean)}. </p> - * - * @param packageName - * The name of the package whose package default assertion status - * is to be set. A <tt>null</tt> value indicates the unnamed - * package that is "current" - * (see section 7.4.2 of - * <cite>The Java™ Language Specification</cite>.) - * - * @param enabled - * <tt>true</tt> if classes loaded by this classloader and - * belonging to the named package or any of its subpackages will - * have assertions enabled by default, <tt>false</tt> if they will - * have assertions disabled by default. - * - * @since 1.4 - */ - public void setPackageAssertionStatus(String packageName, - boolean enabled) { - synchronized (assertionLock) { - if (packageAssertionStatus == null) - initializeJavaAssertionMaps(); - - packageAssertionStatus.put(packageName, enabled); - } - } - - /** - * Sets the desired assertion status for the named top-level class in this - * class loader and any nested classes contained therein. This setting - * takes precedence over the class loader's default assertion status, and - * over any applicable per-package default. This method has no effect if - * the named class has already been initialized. (Once a class is - * initialized, its assertion status cannot change.) - * - * <p> If the named class is not a top-level class, this invocation will - * have no effect on the actual assertion status of any class. </p> - * - * @param className - * The fully qualified class name of the top-level class whose - * assertion status is to be set. - * - * @param enabled - * <tt>true</tt> if the named class is to have assertions - * enabled when (and if) it is initialized, <tt>false</tt> if the - * class is to have assertions disabled. - * - * @since 1.4 - */ - public void setClassAssertionStatus(String className, boolean enabled) { - synchronized (assertionLock) { - if (classAssertionStatus == null) - initializeJavaAssertionMaps(); - - classAssertionStatus.put(className, enabled); - } - } - - /** - * Sets the default assertion status for this class loader to - * <tt>false</tt> and discards any package defaults or class assertion - * status settings associated with the class loader. This method is - * provided so that class loaders can be made to ignore any command line or - * persistent assertion status settings and "start with a clean slate." - * </p> - * - * @since 1.4 - */ - public void clearAssertionStatus() { - /* - * Whether or not "Java assertion maps" are initialized, set - * them to empty maps, effectively ignoring any present settings. - */ - synchronized (assertionLock) { - classAssertionStatus = new HashMap<>(); - packageAssertionStatus = new HashMap<>(); - defaultAssertionStatus = false; - } - } - - /** - * Returns the assertion status that would be assigned to the specified - * class if it were to be initialized at the time this method is invoked. - * If the named class has had its assertion status set, the most recent - * setting will be returned; otherwise, if any package default assertion - * status pertains to this class, the most recent setting for the most - * specific pertinent package default assertion status is returned; - * otherwise, this class loader's default assertion status is returned. - * </p> - * - * @param className - * The fully qualified class name of the class whose desired - * assertion status is being queried. - * - * @return The desired assertion status of the specified class. - * - * @see #setClassAssertionStatus(String, boolean) - * @see #setPackageAssertionStatus(String, boolean) - * @see #setDefaultAssertionStatus(boolean) - * - * @since 1.4 - */ - boolean desiredAssertionStatus(String className) { - synchronized (assertionLock) { - // assert classAssertionStatus != null; - // assert packageAssertionStatus != null; - - // Check for a class entry - Boolean result = classAssertionStatus.get(className); - if (result != null) - return result.booleanValue(); - - // Check for most specific package entry - int dotIndex = className.lastIndexOf("."); - if (dotIndex < 0) { // default package - result = packageAssertionStatus.get(null); - if (result != null) - return result.booleanValue(); - } - while(dotIndex > 0) { - className = className.substring(0, dotIndex); - result = packageAssertionStatus.get(className); - if (result != null) - return result.booleanValue(); - dotIndex = className.lastIndexOf(".", dotIndex-1); - } - - // Return the classloader default - return defaultAssertionStatus; - } - } - - // Set up the assertions with information provided by the VM. - // Note: Should only be called inside a synchronized block - private void initializeJavaAssertionMaps() { - // assert Thread.holdsLock(assertionLock); - - classAssertionStatus = new HashMap<>(); - packageAssertionStatus = new HashMap<>(); - AssertionStatusDirectives directives = retrieveDirectives(); - - for(int i = 0; i < directives.classes.length; i++) - classAssertionStatus.put(directives.classes[i], - directives.classEnabled[i]); - - for(int i = 0; i < directives.packages.length; i++) - packageAssertionStatus.put(directives.packages[i], - directives.packageEnabled[i]); - - defaultAssertionStatus = directives.deflt; - } - - // Retrieves the assertion directives from the VM. - private static native AssertionStatusDirectives retrieveDirectives(); - - // [IKVM] equivalent of HotSpot's java_lang_ClassLoader::is_trusted_loader() - static boolean isTrustedLoader(ClassLoader loader) { - ClassLoader cl = scl; - while (cl != null) { - if (cl == loader) return true; - cl = cl.parent; - } - return false; - } -} - - -class SystemClassLoaderAction - implements PrivilegedExceptionAction<ClassLoader> { - private ClassLoader parent; - - SystemClassLoaderAction(ClassLoader parent) { - this.parent = parent; - } - - public ClassLoader run() throws Exception { - String cls = System.getProperty("java.system.class.loader"); - if (cls == null) { - return parent; - } - - Constructor ctor = Class.forName(cls, true, parent) - .getDeclaredConstructor(new Class[] { ClassLoader.class }); - ClassLoader sys = (ClassLoader) ctor.newInstance( - new Object[] { parent }); - Thread.currentThread().setContextClassLoader(sys); - return sys; - } -} diff --git a/openjdk/java/lang/ClassLoaderHelper.java b/openjdk/java/lang/ClassLoaderHelper.java deleted file mode 100644 index c37c47e8..00000000 --- a/openjdk/java/lang/ClassLoaderHelper.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package java.lang; - -import java.io.File; - -class ClassLoaderHelper { - - private ClassLoaderHelper() {} - - /** - * Returns an alternate path name for the given file - * such that if the original pathname did not exist, then the - * file may be located at the alternate location. - * For mac, this replaces the final .dylib suffix with .jnilib - */ - static File mapAlternativeName(File lib) { - if (ikvm.internal.Util.MACOSX) { - String name = lib.toString(); - int index = name.toLowerCase().lastIndexOf(".dylib"); - if (index < 0) { - return null; - } - return new File(name.substring(0, index) + ".jnilib"); - } else { - return null; - } - } -} diff --git a/openjdk/java/lang/Enum.java b/openjdk/java/lang/Enum.java deleted file mode 100644 index b29550b4..00000000 --- a/openjdk/java/lang/Enum.java +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (c) 2003, 2009, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang; - -import java.io.Serializable; -import java.io.IOException; -import java.io.InvalidObjectException; -import java.io.ObjectInputStream; -import java.io.ObjectStreamException; -import cli.System.Runtime.Serialization.IObjectReference; -import cli.System.Runtime.Serialization.SerializationException; -import cli.System.Runtime.Serialization.SerializationInfo; -import cli.System.Runtime.Serialization.StreamingContext; - -/** - * This is the common base class of all Java language enumeration types. - * - * More information about enums, including descriptions of the - * implicitly declared methods synthesized by the compiler, can be - * found in section 8.9 of - * <cite>The Java™ Language Specification</cite>. - * - * <p> Note that when using an enumeration type as the type of a set - * or as the type of the keys in a map, specialized and efficient - * {@linkplain java.util.EnumSet set} and {@linkplain - * java.util.EnumMap map} implementations are available. - * - * @param <E> The enum type subclass - * @author Josh Bloch - * @author Neal Gafter - * @see Class#getEnumConstants() - * @see java.util.EnumSet - * @see java.util.EnumMap - * @since 1.5 - */ -@cli.System.SerializableAttribute.Annotation -public abstract class Enum<E extends Enum<E>> - implements Comparable<E>, Serializable { - /** - * The name of this enum constant, as declared in the enum declaration. - * Most programmers should use the {@link #toString} method rather than - * accessing this field. - */ - private final String name; - - /** - * Returns the name of this enum constant, exactly as declared in its - * enum declaration. - * - * <b>Most programmers should use the {@link #toString} method in - * preference to this one, as the toString method may return - * a more user-friendly name.</b> This method is designed primarily for - * use in specialized situations where correctness depends on getting the - * exact name, which will not vary from release to release. - * - * @return the name of this enum constant - */ - public final String name() { - return name; - } - - /** - * The ordinal of this enumeration constant (its position - * in the enum declaration, where the initial constant is assigned - * an ordinal of zero). - * - * Most programmers will have no use for this field. It is designed - * for use by sophisticated enum-based data structures, such as - * {@link java.util.EnumSet} and {@link java.util.EnumMap}. - */ - private final int ordinal; - - /** - * Returns the ordinal of this enumeration constant (its position - * in its enum declaration, where the initial constant is assigned - * an ordinal of zero). - * - * Most programmers will have no use for this method. It is - * designed for use by sophisticated enum-based data structures, such - * as {@link java.util.EnumSet} and {@link java.util.EnumMap}. - * - * @return the ordinal of this enumeration constant - */ - public final int ordinal() { - return ordinal; - } - - /** - * Sole constructor. Programmers cannot invoke this constructor. - * It is for use by code emitted by the compiler in response to - * enum type declarations. - * - * @param name - The name of this enum constant, which is the identifier - * used to declare it. - * @param ordinal - The ordinal of this enumeration constant (its position - * in the enum declaration, where the initial constant is assigned - * an ordinal of zero). - */ - protected Enum(String name, int ordinal) { - this.name = name; - this.ordinal = ordinal; - } - - /** - * Returns the name of this enum constant, as contained in the - * declaration. This method may be overridden, though it typically - * isn't necessary or desirable. An enum type should override this - * method when a more "programmer-friendly" string form exists. - * - * @return the name of this enum constant - */ - public String toString() { - return name; - } - - /** - * Returns true if the specified object is equal to this - * enum constant. - * - * @param other the object to be compared for equality with this object. - * @return true if the specified object is equal to this - * enum constant. - */ - public final boolean equals(Object other) { - return this==other; - } - - /** - * Returns a hash code for this enum constant. - * - * @return a hash code for this enum constant. - */ - public final int hashCode() { - return super.hashCode(); - } - - /** - * Throws CloneNotSupportedException. This guarantees that enums - * are never cloned, which is necessary to preserve their "singleton" - * status. - * - * @return (never returns) - */ - protected final Object clone() throws CloneNotSupportedException { - throw new CloneNotSupportedException(); - } - - /** - * Compares this enum with the specified object for order. Returns a - * negative integer, zero, or a positive integer as this object is less - * than, equal to, or greater than the specified object. - * - * Enum constants are only comparable to other enum constants of the - * same enum type. The natural order implemented by this - * method is the order in which the constants are declared. - */ - public final int compareTo(E o) { - Enum other = (Enum)o; - Enum self = this; - if (self.getClass() != other.getClass() && // optimization - self.getDeclaringClass() != other.getDeclaringClass()) - throw new ClassCastException(); - return self.ordinal - other.ordinal; - } - - /** - * Returns the Class object corresponding to this enum constant's - * enum type. Two enum constants e1 and e2 are of the - * same enum type if and only if - * e1.getDeclaringClass() == e2.getDeclaringClass(). - * (The value returned by this method may differ from the one returned - * by the {@link Object#getClass} method for enum constants with - * constant-specific class bodies.) - * - * @return the Class object corresponding to this enum constant's - * enum type - */ - public final Class<E> getDeclaringClass() { - Class clazz = getClass(); - Class zuper = clazz.getSuperclass(); - return (zuper == Enum.class) ? clazz : zuper; - } - - /** - * Returns the enum constant of the specified enum type with the - * specified name. The name must match exactly an identifier used - * to declare an enum constant in this type. (Extraneous whitespace - * characters are not permitted.) - * - * <p>Note that for a particular enum type {@code T}, the - * implicitly declared {@code public static T valueOf(String)} - * method on that enum may be used instead of this method to map - * from a name to the corresponding enum constant. All the - * constants of an enum type can be obtained by calling the - * implicit {@code public static T[] values()} method of that - * type. - * - * @param <T> The enum type whose constant is to be returned - * @param enumType the {@code Class} object of the enum type from which - * to return a constant - * @param name the name of the constant to return - * @return the enum constant of the specified enum type with the - * specified name - * @throws IllegalArgumentException if the specified enum type has - * no constant with the specified name, or the specified - * class object does not represent an enum type - * @throws NullPointerException if {@code enumType} or {@code name} - * is null - * @since 1.5 - */ - public static <T extends Enum<T>> T valueOf(Class<T> enumType, - String name) { - T result = enumType.enumConstantDirectory().get(name); - if (result != null) - return result; - if (name == null) - throw new NullPointerException("Name is null"); - throw new IllegalArgumentException( - "No enum constant " + enumType.getCanonicalName() + "." + name); - } - - /** - * enum classes cannot have finalize methods. - */ - protected final void finalize() { } - - /** - * prevent default deserialization - */ - private void readObject(ObjectInputStream in) throws IOException, - ClassNotFoundException { - throw new InvalidObjectException("can't deserialize enum"); - } - - private void readObjectNoData() throws ObjectStreamException { - throw new InvalidObjectException("can't deserialize enum"); - } - - // [IKVM] .NET serialization support starts here - // Note that we don't have a security demand, because the info is harmless. - @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation - @cli.System.Security.SecurityCriticalAttribute.Annotation - public final void GetObjectData(SerializationInfo info, StreamingContext context) - { - info.AddValue("enumType", getDeclaringClass()); - info.AddValue("name", name); - info.SetType(ikvm.runtime.Util.getInstanceTypeFromClass(EnumSerializationProxy.class)); - } -} - -@cli.System.SerializableAttribute.Annotation -final class EnumSerializationProxy implements IObjectReference -{ - private Class enumType; - private String name; - - @cli.System.Security.SecurityCriticalAttribute.Annotation - public Object GetRealObject(StreamingContext context) - { - try - { - return Enum.valueOf(enumType, name); - } - catch (IllegalArgumentException x) - { - ikvm.runtime.Util.throwException(new SerializationException("Enum value " + name + " not found in " + enumType, x)); - return null; - } - } -} diff --git a/openjdk/java/lang/LangHelper.java b/openjdk/java/lang/LangHelper.java deleted file mode 100644 index 8d725d43..00000000 --- a/openjdk/java/lang/LangHelper.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - Copyright (C) 2007-2014 Jeroen Frijters - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jeroen Frijters - jeroen@frijters.net - -*/ - -package java.lang; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Executable; -import java.security.AccessControlContext; -import java.util.Map; -import sun.nio.ch.Interruptible; -import sun.reflect.annotation.AnnotationType; - -@ikvm.lang.Internal -public class LangHelper -{ - public static sun.misc.JavaLangAccess getJavaLangAccess() - { - return new sun.misc.JavaLangAccess() { - public sun.reflect.ConstantPool getConstantPool(Class klass) { - return klass.getConstantPool(); - } - public boolean casAnnotationType(Class<?> klass, AnnotationType oldType, AnnotationType newType) { - return klass.casAnnotationType(oldType, newType); - } - public AnnotationType getAnnotationType(Class klass) { - return klass.getAnnotationType(); - } - public Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationMap(Class<?> klass) { - return klass.getDeclaredAnnotationMap(); - } - public byte[] getRawClassAnnotations(Class<?> klass) { - throw new InternalError(); - } - public byte[] getRawClassTypeAnnotations(Class<?> klass) { - return klass.getRawTypeAnnotations(); - } - public byte[] getRawExecutableTypeAnnotations(Executable executable) { - return Class.getExecutableTypeAnnotationBytes(executable); - } - public <E extends Enum<E>> - E[] getEnumConstantsShared(Class<E> klass) { - return klass.getEnumConstantsShared(); - } - public void blockedOn(Thread t, Interruptible b) { - t.blockedOn(b); - } - public void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook) { - Shutdown.add(slot, registerShutdownInProgress, hook); - } - public int getStackTraceDepth(Throwable t) { - return t.getStackTraceDepth(); - } - public StackTraceElement getStackTraceElement(Throwable t, int i) { - return t.getStackTraceElement(i); - } - public String newStringUnsafe(char[] chars) { - return String.valueOf(chars); - } - public Thread newThreadWithAcc(Runnable target, AccessControlContext acc) { - return new Thread(target, acc); - } - public void invokeFinalize(Object o) throws Throwable { - // we don't actually support invoking the finalize method explicitly - } - }; - } -} diff --git a/openjdk/java/lang/Package.java b/openjdk/java/lang/Package.java deleted file mode 100644 index 395cf336..00000000 --- a/openjdk/java/lang/Package.java +++ /dev/null @@ -1,615 +0,0 @@ -/* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang; - -import java.io.InputStream; -import java.util.Enumeration; - -import java.util.StringTokenizer; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.net.URL; -import java.net.MalformedURLException; -import java.security.AccessController; -import java.security.PrivilegedAction; - -import java.util.jar.JarInputStream; -import java.util.jar.Manifest; -import java.util.jar.Attributes; -import java.util.jar.Attributes.Name; -import java.util.jar.JarException; -import java.util.Map; -import java.util.HashMap; -import java.util.Iterator; - -import java.lang.annotation.Annotation; -import sun.net.www.ParseUtil; -import sun.reflect.CallerSensitive; -import sun.reflect.Reflection; - -/** - * {@code Package} objects contain version information - * about the implementation and specification of a Java package. - * This versioning information is retrieved and made available - * by the {@link ClassLoader} instance that - * loaded the class(es). Typically, it is stored in the manifest that is - * distributed with the classes. - * - * <p>The set of classes that make up the package may implement a - * particular specification and if so the specification title, version number, - * and vendor strings identify that specification. - * An application can ask if the package is - * compatible with a particular version, see the {@link - * #isCompatibleWith isCompatibleWith} - * method for details. - * - * <p>Specification version numbers use a syntax that consists of nonnegative - * decimal integers separated by periods ".", for example "2.0" or - * "1.2.3.4.5.6.7". This allows an extensible number to be used to represent - * major, minor, micro, etc. versions. The version specification is described - * by the following formal grammar: - * <blockquote> - * <dl> - * <dt><i>SpecificationVersion: - * <dd>Digits RefinedVersion<sub>opt</sub></i> - - * <p><dt><i>RefinedVersion:</i> - * <dd>{@code .} <i>Digits</i> - * <dd>{@code .} <i>Digits RefinedVersion</i> - * - * <p><dt><i>Digits: - * <dd>Digit - * <dd>Digits</i> - * - * <p><dt><i>Digit:</i> - * <dd>any character for which {@link Character#isDigit} returns {@code true}, - * e.g. 0, 1, 2, ... - * </dl> - * </blockquote> - * - * <p>The implementation title, version, and vendor strings identify an - * implementation and are made available conveniently to enable accurate - * reporting of the packages involved when a problem occurs. The contents - * all three implementation strings are vendor specific. The - * implementation version strings have no specified syntax and should - * only be compared for equality with desired version identifiers. - * - * <p>Within each {@code ClassLoader} instance all classes from the same - * java package have the same Package object. The static methods allow a package - * to be found by name or the set of all packages known to the current class - * loader to be found. - * - * @see ClassLoader#definePackage - */ -public class Package implements java.lang.reflect.AnnotatedElement { - /** - * Return the name of this package. - * - * @return The fully-qualified name of this package as defined in section 6.5.3 of - * <cite>The Java™ Language Specification</cite>, - * for example, {@code java.lang} - */ - public String getName() { - return pkgName; - } - - - /** - * Return the title of the specification that this package implements. - * @return the specification title, null is returned if it is not known. - */ - public String getSpecificationTitle() { - return specTitle; - } - - /** - * Returns the version number of the specification - * that this package implements. - * This version string must be a sequence of nonnegative decimal - * integers separated by "."'s and may have leading zeros. - * When version strings are compared the most significant - * numbers are compared. - * @return the specification version, null is returned if it is not known. - */ - public String getSpecificationVersion() { - return specVersion; - } - - /** - * Return the name of the organization, vendor, - * or company that owns and maintains the specification - * of the classes that implement this package. - * @return the specification vendor, null is returned if it is not known. - */ - public String getSpecificationVendor() { - return specVendor; - } - - /** - * Return the title of this package. - * @return the title of the implementation, null is returned if it is not known. - */ - public String getImplementationTitle() { - return implTitle; - } - - /** - * Return the version of this implementation. It consists of any string - * assigned by the vendor of this implementation and does - * not have any particular syntax specified or expected by the Java - * runtime. It may be compared for equality with other - * package version strings used for this implementation - * by this vendor for this package. - * @return the version of the implementation, null is returned if it is not known. - */ - public String getImplementationVersion() { - return implVersion; - } - - /** - * Returns the name of the organization, - * vendor or company that provided this implementation. - * @return the vendor that implemented this package.. - */ - public String getImplementationVendor() { - return implVendor; - } - - /** - * Returns true if this package is sealed. - * - * @return true if the package is sealed, false otherwise - */ - public boolean isSealed() { - return sealBase != null; - } - - /** - * Returns true if this package is sealed with respect to the specified - * code source url. - * - * @param url the code source url - * @return true if this package is sealed with respect to url - */ - public boolean isSealed(URL url) { - return url.equals(sealBase); - } - - /** - * Compare this package's specification version with a - * desired version. It returns true if - * this packages specification version number is greater than or equal - * to the desired version number. <p> - * - * Version numbers are compared by sequentially comparing corresponding - * components of the desired and specification strings. - * Each component is converted as a decimal integer and the values - * compared. - * If the specification value is greater than the desired - * value true is returned. If the value is less false is returned. - * If the values are equal the period is skipped and the next pair of - * components is compared. - * - * @param desired the version string of the desired version. - * @return true if this package's version number is greater - * than or equal to the desired version number - * - * @exception NumberFormatException if the desired or current version - * is not of the correct dotted form. - */ - public boolean isCompatibleWith(String desired) - throws NumberFormatException - { - if (specVersion == null || specVersion.length() < 1) { - throw new NumberFormatException("Empty version string"); - } - - String [] sa = specVersion.split("\\.", -1); - int [] si = new int[sa.length]; - for (int i = 0; i < sa.length; i++) { - si[i] = Integer.parseInt(sa[i]); - if (si[i] < 0) - throw NumberFormatException.forInputString("" + si[i]); - } - - String [] da = desired.split("\\.", -1); - int [] di = new int[da.length]; - for (int i = 0; i < da.length; i++) { - di[i] = Integer.parseInt(da[i]); - if (di[i] < 0) - throw NumberFormatException.forInputString("" + di[i]); - } - - int len = Math.max(di.length, si.length); - for (int i = 0; i < len; i++) { - int d = (i < di.length ? di[i] : 0); - int s = (i < si.length ? si[i] : 0); - if (s < d) - return false; - if (s > d) - return true; - } - return true; - } - - /** - * Find a package by name in the callers {@code ClassLoader} instance. - * The callers {@code ClassLoader} instance is used to find the package - * instance corresponding to the named class. If the callers - * {@code ClassLoader} instance is null then the set of packages loaded - * by the system {@code ClassLoader} instance is searched to find the - * named package. <p> - * - * Packages have attributes for versions and specifications only if the class - * loader created the package instance with the appropriate attributes. Typically, - * those attributes are defined in the manifests that accompany the classes. - * - * @param name a package name, for example, java.lang. - * @return the package of the requested name. It may be null if no package - * information is available from the archive or codebase. - */ - @CallerSensitive - public static Package getPackage(String name) { - ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass()); - if (l != null) { - return l.getPackage(name); - } else { - return getSystemPackage(name); - } - } - - /** - * Get all the packages currently known for the caller's {@code ClassLoader} - * instance. Those packages correspond to classes loaded via or accessible by - * name to that {@code ClassLoader} instance. If the caller's - * {@code ClassLoader} instance is the bootstrap {@code ClassLoader} - * instance, which may be represented by {@code null} in some implementations, - * only packages corresponding to classes loaded by the bootstrap - * {@code ClassLoader} instance will be returned. - * - * @return a new array of packages known to the callers {@code ClassLoader} - * instance. An zero length array is returned if none are known. - */ - @CallerSensitive - public static Package[] getPackages() { - ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass()); - if (l != null) { - return l.getPackages(); - } else { - return getSystemPackages(); - } - } - - /** - * Get the package for the specified class. - * The class's class loader is used to find the package instance - * corresponding to the specified class. If the class loader - * is the bootstrap class loader, which may be represented by - * {@code null} in some implementations, then the set of packages - * loaded by the bootstrap class loader is searched to find the package. - * <p> - * Packages have attributes for versions and specifications only - * if the class loader created the package - * instance with the appropriate attributes. Typically those - * attributes are defined in the manifests that accompany - * the classes. - * - * @param class the class to get the package of. - * @return the package of the class. It may be null if no package - * information is available from the archive or codebase. */ - static Package getPackage(Class<?> c) { - String name = c.getName(); - int i = name.lastIndexOf('.'); - if (i != -1) { - name = name.substring(0, i); - ClassLoader cl = c.getClassLoader(); - if (cl != null) { - return cl.getPackage(name); - } else { - return getSystemPackage(name); - } - } else { - return null; - } - } - - /** - * Return the hash code computed from the package name. - * @return the hash code computed from the package name. - */ - public int hashCode(){ - return pkgName.hashCode(); - } - - /** - * Returns the string representation of this Package. - * Its value is the string "package " and the package name. - * If the package title is defined it is appended. - * If the package version is defined it is appended. - * @return the string representation of the package. - */ - public String toString() { - String spec = specTitle; - String ver = specVersion; - if (spec != null && spec.length() > 0) - spec = ", " + spec; - else - spec = ""; - if (ver != null && ver.length() > 0) - ver = ", version " + ver; - else - ver = ""; - return "package " + pkgName + spec + ver; - } - - private Class<?> getPackageInfo() { - if (packageInfo == null) { - try { - packageInfo = Class.forName(pkgName + ".package-info", false, loader); - } catch (ClassNotFoundException ex) { - // store a proxy for the package info that has no annotations - class PackageInfoProxy {} - packageInfo = PackageInfoProxy.class; - } - } - return packageInfo; - } - - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.5 - */ - public <A extends Annotation> A getAnnotation(Class<A> annotationClass) { - return getPackageInfo().getAnnotation(annotationClass); - } - - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.5 - */ - public boolean isAnnotationPresent( - Class<? extends Annotation> annotationClass) { - return getPackageInfo().isAnnotationPresent(annotationClass); - } - - /** - * @since 1.5 - */ - public Annotation[] getAnnotations() { - return getPackageInfo().getAnnotations(); - } - - /** - * @since 1.5 - */ - public Annotation[] getDeclaredAnnotations() { - return getPackageInfo().getDeclaredAnnotations(); - } - - /** - * Construct a package instance with the specified version - * information. - * @param pkgName the name of the package - * @param spectitle the title of the specification - * @param specversion the version of the specification - * @param specvendor the organization that maintains the specification - * @param impltitle the title of the implementation - * @param implversion the version of the implementation - * @param implvendor the organization that maintains the implementation - * @return a new package for containing the specified information. - */ - Package(String name, - String spectitle, String specversion, String specvendor, - String impltitle, String implversion, String implvendor, - URL sealbase, ClassLoader loader) - { - pkgName = name; - implTitle = impltitle; - implVersion = implversion; - implVendor = implvendor; - specTitle = spectitle; - specVersion = specversion; - specVendor = specvendor; - sealBase = sealbase; - this.loader = loader; - } - - /* - * Construct a package using the attributes from the specified manifest. - * - * @param name the package name - * @param man the optional manifest for the package - * @param url the optional code source url for the package - */ - private Package(String name, Manifest man, URL url, ClassLoader loader) { - String path = name.replace('.', '/').concat("/"); - String sealed = null; - String specTitle= null; - String specVersion= null; - String specVendor= null; - String implTitle= null; - String implVersion= null; - String implVendor= null; - URL sealBase= null; - Attributes attr = man.getAttributes(path); - if (attr != null) { - specTitle = attr.getValue(Name.SPECIFICATION_TITLE); - specVersion = attr.getValue(Name.SPECIFICATION_VERSION); - specVendor = attr.getValue(Name.SPECIFICATION_VENDOR); - implTitle = attr.getValue(Name.IMPLEMENTATION_TITLE); - implVersion = attr.getValue(Name.IMPLEMENTATION_VERSION); - implVendor = attr.getValue(Name.IMPLEMENTATION_VENDOR); - sealed = attr.getValue(Name.SEALED); - } - attr = man.getMainAttributes(); - if (attr != null) { - if (specTitle == null) { - specTitle = attr.getValue(Name.SPECIFICATION_TITLE); - } - if (specVersion == null) { - specVersion = attr.getValue(Name.SPECIFICATION_VERSION); - } - if (specVendor == null) { - specVendor = attr.getValue(Name.SPECIFICATION_VENDOR); - } - if (implTitle == null) { - implTitle = attr.getValue(Name.IMPLEMENTATION_TITLE); - } - if (implVersion == null) { - implVersion = attr.getValue(Name.IMPLEMENTATION_VERSION); - } - if (implVendor == null) { - implVendor = attr.getValue(Name.IMPLEMENTATION_VENDOR); - } - if (sealed == null) { - sealed = attr.getValue(Name.SEALED); - } - } - if ("true".equalsIgnoreCase(sealed)) { - sealBase = url; - } - pkgName = name; - this.specTitle = specTitle; - this.specVersion = specVersion; - this.specVendor = specVendor; - this.implTitle = implTitle; - this.implVersion = implVersion; - this.implVendor = implVendor; - this.sealBase = sealBase; - this.loader = loader; - } - - /* - * Returns the loaded system package for the specified name. - */ - static Package getSystemPackage(String name) { - synchronized (pkgs) { - Package pkg = pkgs.get(name); - if (pkg == null) { - name = name.replace('.', '/').concat("/"); - String fn = getSystemPackage0(name); - if (fn != null) { - pkg = defineSystemPackage(name, fn); - } - } - return pkg; - } - } - - /* - * Return an array of loaded system packages. - */ - static Package[] getSystemPackages() { - // First, update the system package map with new package names - String[] names = getSystemPackages0(); - synchronized (pkgs) { - for (int i = 0; i < names.length; i++) { - defineSystemPackage(names[i], getSystemPackage0(names[i])); - } - return pkgs.values().toArray(new Package[pkgs.size()]); - } - } - - private static Package defineSystemPackage(final String iname, - final String fn) - { - return AccessController.doPrivileged(new PrivilegedAction<Package>() { - public Package run() { - String name = iname; - // Get the cached code source url for the file name - URL url = urls.get(fn); - if (url == null) { - // URL not found, so create one - File file = new File(fn); - try { - url = ParseUtil.fileToEncodedURL(file); - } catch (MalformedURLException e) { - } - if (url != null) { - urls.put(fn, url); - // If loading a JAR file, then also cache the manifest - if (file.isFile()) { - mans.put(fn, loadManifest(fn)); - } - } - } - // Convert to "."-separated package name - name = name.substring(0, name.length() - 1).replace('/', '.'); - Package pkg; - Manifest man = mans.get(fn); - if (man != null) { - pkg = new Package(name, man, url, null); - } else { - pkg = new Package(name, null, null, null, - null, null, null, null, null); - } - pkgs.put(name, pkg); - return pkg; - } - }); - } - - /* - * Returns the Manifest for the specified JAR file name. - */ - private static Manifest loadManifest(String fn) { - try (FileInputStream fis = new FileInputStream(fn); - JarInputStream jis = new JarInputStream(fis, false)) - { - return jis.getManifest(); - } catch (IOException e) { - return null; - } - } - - // The map of loaded system packages - private static Map<String, Package> pkgs = new HashMap<>(31); - - // Maps each directory or zip file name to its corresponding url - private static Map<String, URL> urls = new HashMap<>(10); - - // Maps each code source url for a jar file to its manifest - private static Map<String, Manifest> mans = new HashMap<>(10); - - private static native String getSystemPackage0(String name); - private static native String[] getSystemPackages0(); - - /* - * Private storage for the package name and attributes. - */ - private final String pkgName; - private final String specTitle; - private final String specVersion; - private final String specVendor; - private final String implTitle; - private final String implVersion; - private final String implVendor; - private final URL sealBase; - private transient final ClassLoader loader; - private transient Class packageInfo; -} diff --git a/openjdk/java/lang/ProcessImpl.java b/openjdk/java/lang/ProcessImpl.java deleted file mode 100644 index 0624dc17..00000000 --- a/openjdk/java/lang/ProcessImpl.java +++ /dev/null @@ -1,834 +0,0 @@ -/* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/*IKVM*/ -/* - * Modified for IKVM by Jeroen Frijters - */ - -package java.lang; - -import java.io.IOException; -import java.io.File; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileDescriptor; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.lang.ProcessBuilder.Redirect; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import cli.System.AsyncCallback; -import cli.System.IAsyncResult; -import cli.System.Diagnostics.ProcessStartInfo; -import cli.System.EventArgs; -import cli.System.EventHandler; -import cli.System.IO.FileAccess; -import cli.System.IO.FileShare; -import cli.System.IO.FileMode; -import cli.System.IO.FileOptions; -import cli.System.IO.FileStream; -import cli.System.IO.Stream; -import cli.System.Security.AccessControl.FileSystemRights; - -/* This class is for the exclusive use of ProcessBuilder.start() to - * create new processes. - * - * @author Martin Buchholz - * @since 1.5 - */ - -final class ProcessImpl extends Process { - static class fdAccess { - static Stream getHandle(FileDescriptor fd) { - return fd.getStream(); - } - } - - /** - * Open a file for writing. If {@code append} is {@code true} then the file - * is opened for atomic append directly and a FileOutputStream constructed - * with the resulting handle. This is because a FileOutputStream created - * to append to a file does not open the file in a manner that guarantees - * that writes by the child process will be atomic. - */ - private static FileOutputStream newFileOutputStream(File f, boolean append) - throws IOException - { - if (append) { - String path = f.getPath(); - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkWrite(path); - final FileDescriptor fd = openForAtomicAppend(path); - return AccessController.doPrivileged( - new PrivilegedAction<FileOutputStream>() { - public FileOutputStream run() { - return new FileOutputStream(fd); - } - } - ); - } else { - return new FileOutputStream(f); - } - } - - // System-dependent portion of ProcessBuilder.start() - static Process start(String cmdarray[], - java.util.Map<String,String> environment, - String dir, - ProcessBuilder.Redirect[] redirects, - boolean redirectErrorStream) - throws IOException - { - FileInputStream f0 = null; - FileOutputStream f1 = null; - FileOutputStream f2 = null; - - try { - Stream[] stdHandles; - if (redirects == null) { - stdHandles = new Stream[3]; - } else { - stdHandles = new Stream[3]; - - if (redirects[0] == Redirect.PIPE) - stdHandles[0] = null; - else if (redirects[0] == Redirect.INHERIT) - stdHandles[0] = fdAccess.getHandle(FileDescriptor.in); - else { - f0 = new FileInputStream(redirects[0].file()); - stdHandles[0] = fdAccess.getHandle(f0.getFD()); - } - - if (redirects[1] == Redirect.PIPE) - stdHandles[1] = null; - else if (redirects[1] == Redirect.INHERIT) - stdHandles[1] = fdAccess.getHandle(FileDescriptor.out); - else { - f1 = newFileOutputStream(redirects[1].file(), - redirects[1].append()); - stdHandles[1] = fdAccess.getHandle(f1.getFD()); - } - - if (redirects[2] == Redirect.PIPE) - stdHandles[2] = null; - else if (redirects[2] == Redirect.INHERIT) - stdHandles[2] = fdAccess.getHandle(FileDescriptor.err); - else { - f2 = newFileOutputStream(redirects[2].file(), - redirects[2].append()); - stdHandles[2] = fdAccess.getHandle(f2.getFD()); - } - } - - return new ProcessImpl(cmdarray, environment, dir, - stdHandles, redirectErrorStream); - } catch (Throwable t) { - if (f0 != null) - f0.close(); - if (f1 != null) - f1.close(); - if (f2 != null) - f2.close(); - throw t; - } finally { - // HACK prevent the File[In|Out]putStream objects from closing the streams - // (the System.IO.FileStream will eventually be closed explicitly or by its finalizer) - if (f0 != null) - cli.System.GC.SuppressFinalize(f0); - if (f1 != null) - cli.System.GC.SuppressFinalize(f1); - if (f2 != null) - cli.System.GC.SuppressFinalize(f2); - } - - } - - private static class LazyPattern { - // Escape-support version: - // "(\")((?:\\\\\\1|.)+?)\\1|([^\\s\"]+)"; - private static final Pattern PATTERN = - Pattern.compile("[^\\s\"]+|\"[^\"]*\""); - }; - - /* Parses the command string parameter into the executable name and - * program arguments. - * - * The command string is broken into tokens. The token separator is a space - * or quota character. The space inside quotation is not a token separator. - * There are no escape sequences. - */ - private static String[] getTokensFromCommand(String command) { - ArrayList<String> matchList = new ArrayList<>(8); - Matcher regexMatcher = LazyPattern.PATTERN.matcher(command); - while (regexMatcher.find()) - matchList.add(regexMatcher.group()); - return matchList.toArray(new String[matchList.size()]); - } - - private static final int VERIFICATION_CMD_BAT = 0; - private static final int VERIFICATION_WIN32 = 1; - private static final int VERIFICATION_LEGACY = 2; - private static final char ESCAPE_VERIFICATION[][] = { - // We guarantee the only command file execution for implicit [cmd.exe] run. - // http://technet.microsoft.com/en-us/library/bb490954.aspx - {' ', '\t', '<', '>', '&', '|', '^'}, - - {' ', '\t', '<', '>'}, - {' ', '\t'} - }; - - private static String createCommandLine(int verificationType, - final String executablePath, - final String cmd[]) - { - StringBuilder cmdbuf = new StringBuilder(80); - - cmdbuf.append(executablePath); - - for (int i = 1; i < cmd.length; ++i) { - cmdbuf.append(' '); - String s = cmd[i]; - if (needsEscaping(verificationType, s)) { - cmdbuf.append('"').append(s); - - // The code protects the [java.exe] and console command line - // parser, that interprets the [\"] combination as an escape - // sequence for the ["] char. - // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx - // - // If the argument is an FS path, doubling of the tail [\] - // char is not a problem for non-console applications. - // - // The [\"] sequence is not an escape sequence for the [cmd.exe] - // command line parser. The case of the [""] tail escape - // sequence could not be realized due to the argument validation - // procedure. - if ((verificationType != VERIFICATION_CMD_BAT) && s.endsWith("\\")) { - cmdbuf.append('\\'); - } - cmdbuf.append('"'); - } else { - cmdbuf.append(s); - } - } - return cmdbuf.toString(); - } - - private static boolean isQuoted(boolean noQuotesInside, String arg, - String errorMessage) { - int lastPos = arg.length() - 1; - if (lastPos >=1 && arg.charAt(0) == '"' && arg.charAt(lastPos) == '"') { - // The argument has already been quoted. - if (noQuotesInside) { - if (arg.indexOf('"', 1) != lastPos) { - // There is ["] inside. - throw new IllegalArgumentException(errorMessage); - } - } - return true; - } - if (noQuotesInside) { - if (arg.indexOf('"') >= 0) { - // There is ["] inside. - throw new IllegalArgumentException(errorMessage); - } - } - return false; - } - - private static boolean needsEscaping(int verificationType, String arg) { - // Switch off MS heuristic for internal ["]. - // Please, use the explicit [cmd.exe] call - // if you need the internal ["]. - // Example: "cmd.exe", "/C", "Extended_MS_Syntax" - - // For [.exe] or [.com] file the unpaired/internal ["] - // in the argument is not a problem. - boolean argIsQuoted = isQuoted( - (verificationType == VERIFICATION_CMD_BAT), - arg, "Argument has embedded quote, use the explicit CMD.EXE call."); - - if (!argIsQuoted) { - char testEscape[] = ESCAPE_VERIFICATION[verificationType]; - for (int i = 0; i < testEscape.length; ++i) { - if (arg.indexOf(testEscape[i]) >= 0) { - return true; - } - } - } - return false; - } - - private static String getExecutablePath(String path) - throws IOException - { - boolean pathIsQuoted = isQuoted(true, path, - "Executable name has embedded quote, split the arguments"); - - // Win32 CreateProcess requires path to be normalized - File fileToRun = new File(pathIsQuoted - ? path.substring(1, path.length() - 1) - : path); - - // From the [CreateProcess] function documentation: - // - // "If the file name does not contain an extension, .exe is appended. - // Therefore, if the file name extension is .com, this parameter - // must include the .com extension. If the file name ends in - // a period (.) with no extension, or if the file name contains a path, - // .exe is not appended." - // - // "If the file name !does not contain a directory path!, - // the system searches for the executable file in the following - // sequence:..." - // - // In practice ANY non-existent path is extended by [.exe] extension - // in the [CreateProcess] funcion with the only exception: - // the path ends by (.) - - return fileToRun.getPath(); - } - - - private boolean isShellFile(String executablePath) { - String upPath = executablePath.toUpperCase(); - return (upPath.endsWith(".CMD") || upPath.endsWith(".BAT")); - } - - private String quoteString(String arg) { - StringBuilder argbuf = new StringBuilder(arg.length() + 2); - return argbuf.append('"').append(arg).append('"').toString(); - } - - - private cli.System.Diagnostics.Process handle; - private OutputStream stdin_stream; - private InputStream stdout_stream; - private InputStream stderr_stream; - - private ProcessImpl(String cmd[], - final java.util.Map<String,String> envblock, - final String path, - final Stream[] stdHandles, - final boolean redirectErrorStream) - throws IOException - { - String cmdstr; - SecurityManager security = System.getSecurityManager(); - boolean allowAmbiguousCommands = false; - if (security == null) { - allowAmbiguousCommands = true; - String value = System.getProperty("jdk.lang.Process.allowAmbiguousCommands"); - if (value != null) - allowAmbiguousCommands = !"false".equalsIgnoreCase(value); - } - if (allowAmbiguousCommands) { - // Legacy mode. - - // Normalize path if possible. - String executablePath = new File(cmd[0]).getPath(); - - // No worry about internal, unpaired ["], and redirection/piping. - if (needsEscaping(VERIFICATION_LEGACY, executablePath) ) - executablePath = quoteString(executablePath); - - cmdstr = createCommandLine( - //legacy mode doesn't worry about extended verification - VERIFICATION_LEGACY, - executablePath, - cmd); - } else { - String executablePath; - try { - executablePath = getExecutablePath(cmd[0]); - } catch (IllegalArgumentException e) { - // Workaround for the calls like - // Runtime.getRuntime().exec("\"C:\\Program Files\\foo\" bar") - - // No chance to avoid CMD/BAT injection, except to do the work - // right from the beginning. Otherwise we have too many corner - // cases from - // Runtime.getRuntime().exec(String[] cmd [, ...]) - // calls with internal ["] and escape sequences. - - // Restore original command line. - StringBuilder join = new StringBuilder(); - // terminal space in command line is ok - for (String s : cmd) - join.append(s).append(' '); - - // Parse the command line again. - cmd = getTokensFromCommand(join.toString()); - executablePath = getExecutablePath(cmd[0]); - - // Check new executable name once more - if (security != null) - security.checkExec(executablePath); - } - - // Quotation protects from interpretation of the [path] argument as - // start of longer path with spaces. Quotation has no influence to - // [.exe] extension heuristic. - cmdstr = createCommandLine( - // We need the extended verification procedure for CMD files. - isShellFile(executablePath) - ? VERIFICATION_CMD_BAT - : VERIFICATION_WIN32, - quoteString(executablePath), - cmd); - } - - handle = create(cmdstr, envblock, path, - stdHandles, redirectErrorStream); - - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Void>() { - public Void run() { - if (stdHandles[0] == null) - stdin_stream = ProcessBuilder.NullOutputStream.INSTANCE; - else { - FileDescriptor stdin_fd = FileDescriptor.fromStream(stdHandles[0]); - stdin_stream = new BufferedOutputStream( - new FileOutputStream(stdin_fd)); - } - - if (stdHandles[1] == null) - stdout_stream = ProcessBuilder.NullInputStream.INSTANCE; - else { - FileDescriptor stdout_fd = FileDescriptor.fromStream(stdHandles[1]); - stdout_stream = new BufferedInputStream( - new FileInputStream(stdout_fd)); - } - - if (stdHandles[2] == null) - stderr_stream = ProcessBuilder.NullInputStream.INSTANCE; - else { - FileDescriptor stderr_fd = FileDescriptor.fromStream(stdHandles[2]); - stderr_stream = new FileInputStream(stderr_fd); - } - - return null; }}); - } - - private static native String mapVfsExecutable(String path); - - public OutputStream getOutputStream() { - return stdin_stream; - } - - public InputStream getInputStream() { - return stdout_stream; - } - - public InputStream getErrorStream() { - return stderr_stream; - } - - public int exitValue() { - if (!handle.get_HasExited()) - throw new IllegalThreadStateException("process has not exited"); - return handle.get_ExitCode(); - } - - public int waitFor() throws InterruptedException { - waitForInterruptibly(handle); - if (Thread.interrupted()) - throw new InterruptedException(); - return exitValue(); - } - - private static void waitForInterruptibly(cli.System.Diagnostics.Process handle) throws InterruptedException { - // to be interruptable we have to use polling - // (on .NET 2.0 WaitForExit is actually interruptible, but this isn't documented) - Thread current = Thread.currentThread(); - while (!current.isInterrupted() && !handle.WaitForExit(100)) - ; - } - - @Override - public boolean waitFor(long timeout, TimeUnit unit) - throws InterruptedException - { - if (handle.get_HasExited()) return true; - if (timeout <= 0) return false; - - long msTimeout = unit.toMillis(timeout); - - waitForTimeoutInterruptibly(handle, msTimeout); - if (Thread.interrupted()) - throw new InterruptedException(); - return handle.get_HasExited(); - } - - private static void waitForTimeoutInterruptibly( - cli.System.Diagnostics.Process handle, long timeout) { - long now = System.currentTimeMillis(); - long exp = now + timeout; - if (exp < now) { - // if we overflowed, just wait for a really long time - exp = Long.MAX_VALUE; - } - Thread current = Thread.currentThread(); - for (;;) { - if (current.isInterrupted()) { - return; - } - // wait for a maximum of 100 ms to be interruptible - if (handle.WaitForExit((int)Math.min(100, exp - now))) { - return; - } - now = System.currentTimeMillis(); - if (now >= exp) { - return; - } - } - } - - public void destroy() { terminateProcess(handle); } - - @Override - public Process destroyForcibly() { - destroy(); - return this; - } - - private static void terminateProcess(cli.System.Diagnostics.Process handle) { - try { - if (false) throw new cli.System.ComponentModel.Win32Exception(); - if (false) throw new cli.System.InvalidOperationException(); - handle.Kill(); - } catch (cli.System.ComponentModel.Win32Exception _) { - } catch (cli.System.InvalidOperationException _) { - } - } - - @Override - public boolean isAlive() { - return isProcessAlive(handle); - } - - private static boolean isProcessAlive(cli.System.Diagnostics.Process handle) { - return !handle.get_HasExited(); - } - - /** - * Create a process using the win32 function CreateProcess. - * The method is synchronized due to MS kb315939 problem. - * All native handles should restore the inherit flag at the end of call. - * - * @param cmdstr the Windows command line - * @param envblock NUL-separated, double-NUL-terminated list of - * environment strings in VAR=VALUE form - * @param dir the working directory of the process, or null if - * inheriting the current directory from the parent process - * @param stdHandles array of windows HANDLEs. Indexes 0, 1, and - * 2 correspond to standard input, standard output and - * standard error, respectively. On input, a value of -1 - * means to create a pipe to connect child and parent - * processes. On output, a value which is not -1 is the - * parent pipe handle corresponding to the pipe which has - * been created. An element of this array is -1 on input - * if and only if it is <em>not</em> -1 on output. - * @param redirectErrorStream redirectErrorStream attribute - * @return the native subprocess HANDLE returned by CreateProcess - */ - private static cli.System.Diagnostics.Process create(String cmdstr, - java.util.Map<String,String> envblock, - String dir, - Stream[] stdHandles, - boolean redirectErrorStream) - throws IOException { - - int programEnd = parseCommandString(cmdstr); - int argumentsStart = programEnd; - if (cmdstr.length() > argumentsStart && cmdstr.charAt(argumentsStart) == ' ') { - argumentsStart++; - } - - String fileName = cmdstr.substring(0, programEnd); - ProcessStartInfo si = new ProcessStartInfo(mapVfsExecutable(fileName), cmdstr.substring(argumentsStart)); - si.set_UseShellExecute(false); - si.set_RedirectStandardError(true); - si.set_RedirectStandardOutput(true); - si.set_RedirectStandardInput(true); - si.set_CreateNoWindow(true); - if (dir != null) { - si.set_WorkingDirectory(dir); - } - if (envblock != null) { - si.get_EnvironmentVariables().Clear(); - for (String key : envblock.keySet()) { - si.get_EnvironmentVariables().set_Item(key, envblock.get(key)); - } - } - - cli.System.Diagnostics.Process proc; - try { - if (false) throw new cli.System.ComponentModel.Win32Exception(); - if (false) throw new cli.System.InvalidOperationException(); - proc = cli.System.Diagnostics.Process.Start(si); - } catch (cli.System.ComponentModel.Win32Exception x1) { - throw new IOException(x1.getMessage()); - } catch (cli.System.InvalidOperationException x2) { - throw new IOException(x2.getMessage()); - } - - // if any of the handles is redirected to/from a file, - // we need to close the files as soon as the process exits - if (stdHandles[0] instanceof FileStream - || stdHandles[1] instanceof FileStream - || stdHandles[2] instanceof FileStream) { - final Stream s0 = stdHandles[0]; - final Stream s1 = stdHandles[1]; - final Stream s2 = stdHandles[2]; - proc.set_EnableRaisingEvents(true); - proc.add_Exited(new EventHandler(new EventHandler.Method() { - public void Invoke(Object sender, EventArgs e) { - if (s0 instanceof FileStream) - s0.Close(); - if (s1 instanceof FileStream) - s1.Close(); - if (s2 instanceof FileStream) - s2.Close(); - } - })); - } - - Stream stdin = proc.get_StandardInput().get_BaseStream(); - Stream stdout = proc.get_StandardOutput().get_BaseStream(); - Stream stderr = proc.get_StandardError().get_BaseStream(); - - if (stdHandles[0] != null) { - connectPipe(stdHandles[0], stdin); - stdHandles[0] = null; - } else { - stdHandles[0] = stdin; - } - - Stream stdoutDrain = null; - if (stdHandles[1] != null) { - stdoutDrain = stdHandles[1]; - connectPipe(stdout, stdoutDrain); - stdHandles[1] = null; - } else if (redirectErrorStream) { - PipeStream pipe = new PipeStream(); - connectPipe(stdout, pipe); - connectPipe(stderr, pipe); - stdHandles[1] = pipe; - } else { - stdHandles[1] = stdout; - } - - if (redirectErrorStream) { - if (stdoutDrain != null) { - connectPipe(stderr, stdoutDrain); - } - stdHandles[2] = null; - } else if (stdHandles[2] != null) { - connectPipe(stderr, stdHandles[2]); - stdHandles[2] = null; - } else { - stdHandles[2] = stderr; - } - - return proc; - } - - private static final class PipeStream extends Stream - { - private final byte[] buf = new byte[4096]; - private int pos; - private int users = 2; - - @Override - public synchronized int Read(byte[] buffer, int offset, int count) - { - if (count == 0) - { - return 0; - } - while (pos == 0) - { - try - { - wait(); - } - catch (InterruptedException _) { } - } - if (pos == -1) - { - return 0; - } - count = Math.min(count, pos); - System.arraycopy(buf, 0, buffer, offset, count); - pos -= count; - System.arraycopy(buf, count, buf, 0, pos); - notifyAll(); - return count; - } - - @Override - public synchronized void Write(byte[] buffer, int offset, int count) - { - while (buf.length - pos < count) - { - try - { - wait(); - } - catch (InterruptedException _) { } - } - System.arraycopy(buffer, offset, buf, pos, count); - pos += count; - notifyAll(); - } - - @Override - public synchronized void Close() - { - if (--users == 0) - { - pos = -1; - notifyAll(); - } - } - - @Override - public boolean get_CanRead() - { - return true; - } - - @Override - public boolean get_CanSeek() - { - return false; - } - - @Override - public boolean get_CanWrite() - { - return true; - } - - @Override - public void Flush() - { - } - - @Override - public long get_Length() - { - ikvm.runtime.Util.throwException(new cli.System.NotSupportedException()); - return 0; - } - - @Override - public long get_Position() - { - ikvm.runtime.Util.throwException(new cli.System.NotSupportedException()); - return 0; - } - - @Override - public long Seek(long offset, cli.System.IO.SeekOrigin origin) - { - ikvm.runtime.Util.throwException(new cli.System.NotSupportedException()); - return 0; - } - - @Override - public void SetLength(long value) - { - ikvm.runtime.Util.throwException(new cli.System.NotSupportedException()); - } - - @Override - public void set_Position(long position) - { - ikvm.runtime.Util.throwException(new cli.System.NotSupportedException()); - } - } - - private static native int parseCommandString(String cmdstr); - - /** - * Opens a file for atomic append. The file is created if it doesn't - * already exist. - * - * @param file the file to open or create - * @return the native HANDLE - */ - private static FileDescriptor openForAtomicAppend(String path) - throws IOException { - try { - if (false) throw new cli.System.ArgumentException(); - if (false) throw new cli.System.IO.IOException(); - if (false) throw new cli.System.Security.SecurityException(); - if (false) throw new cli.System.UnauthorizedAccessException(); - return FileDescriptor.fromStream(new FileStream(path, FileMode.wrap(FileMode.Append), FileSystemRights.wrap(FileSystemRights.AppendData), FileShare.wrap(FileShare.ReadWrite), 1, FileOptions.wrap(FileOptions.None))); - } catch (cli.System.ArgumentException x) { - throw new IOException(x.getMessage()); - } catch (cli.System.IO.IOException x) { - throw new IOException(x.getMessage()); - } catch (cli.System.Security.SecurityException x) { - throw new IOException(x.getMessage()); - } catch (cli.System.UnauthorizedAccessException x) { - throw new IOException(x.getMessage()); - } - } - - private static void connectPipe(final Stream in, final Stream out) { - final byte[] buf = new byte[4096]; - final AsyncCallback[] callback = new AsyncCallback[1]; - callback[0] = new AsyncCallback(new AsyncCallback.Method() { - public void Invoke(IAsyncResult ar) { - try { - int count = in.EndRead(ar); - if (count > 0) { - out.Write(buf, 0, count); - out.Flush(); - in.BeginRead(buf, 0, buf.length, callback[0], null); - } else { - out.Close(); - } - } catch (Throwable _) { - } - } - }); - try { - in.BeginRead(buf, 0, buf.length, callback[0], null); - } catch (Throwable _) { - } - } -} diff --git a/openjdk/java/lang/PropertyConstants.java.in b/openjdk/java/lang/PropertyConstants.java.in deleted file mode 100644 index 69e7796f..00000000 --- a/openjdk/java/lang/PropertyConstants.java.in +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright (C) 2007, 2009 Jeroen Frijters - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jeroen Frijters - jeroen@frijters.net - -*/ -package java.lang; - -interface PropertyConstants -{ - String awt_toolkit = "ikvm.awt.NetToolkit, @AWTASSEMBLY@"; - String java_awt_graphicsenv = "ikvm.awt.NetGraphicsEnvironment, @AWTASSEMBLY@"; - String java_vm_version = "@VERSION@"; - String java_runtime_version = "@VERSION@"; - String openjdk_version = "@OPENJDK_VERSION@"; -} diff --git a/openjdk/java/lang/Shutdown.java b/openjdk/java/lang/Shutdown.java deleted file mode 100644 index 947f0e39..00000000 --- a/openjdk/java/lang/Shutdown.java +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (c) 1999, 2005, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang; - -import cli.System.AppDomain; -import cli.System.EventArgs; -import cli.System.EventHandler; -import cli.System.Threading.Monitor; - -/** - * Package-private utility class containing data structures and logic - * governing the virtual-machine shutdown sequence. - * - * @author Mark Reinhold - * @since 1.3 - */ - -class Shutdown { - - /* Shutdown state */ - private static final int RUNNING = 0; - private static final int HOOKS = 1; - private static final int FINALIZERS = 2; - private static int state = RUNNING; - - /* Should we run all finalizers upon exit? */ - static volatile boolean runFinalizersOnExit = false; - - // The system shutdown hooks are registered with a predefined slot. - // The list of shutdown hooks is as follows: - // (0) Console restore hook - // (1) Application hooks - // (2) DeleteOnExit hook - private static final int MAX_SYSTEM_HOOKS = 10; - private static final Runnable[] hooks = new Runnable[MAX_SYSTEM_HOOKS]; - - // the index of the currently running shutdown hook to the hooks array - private static int currentRunningHook = 0; - - // [IKVM] have we registered the AppDomain.ProcessExit event handler? - private static boolean registeredProcessExit; - - /* The preceding static fields are protected by this lock */ - private static class Lock { }; - private static Object lock = new Lock(); - - /* Lock object for the native halt method */ - private static Object haltLock = new Lock(); - - /* Invoked by Runtime.runFinalizersOnExit */ - static void setRunFinalizersOnExit(boolean run) { - synchronized (lock) { - runFinalizersOnExit = run; - } - } - - private static void registerProcessExit() { - try { - // MONOBUG Mono doesn't support starting a new thread during ProcessExit - // (and application shutdown hooks are based on threads) - // see https://bugzilla.xamarin.com/show_bug.cgi?id=5650 - if (!ikvm.internal.Util.MONO) { - // AppDomain.ProcessExit has a LinkDemand, so we have to have a separate method - registerShutdownHook(); - if (false) throw new cli.System.Security.SecurityException(); - } - } - catch (cli.System.Security.SecurityException _) { - } - } - - private static void registerShutdownHook() - { - AppDomain.get_CurrentDomain().add_ProcessExit(new EventHandler(new EventHandler.Method() { - public void Invoke(Object sender, EventArgs e) { - shutdown(); - } - })); - } - - /** - * Add a new shutdown hook. Checks the shutdown state and the hook itself, - * but does not do any security checks. - * - * The registerShutdownInProgress parameter should be false except - * registering the DeleteOnExitHook since the first file may - * be added to the delete on exit list by the application shutdown - * hooks. - * - * @params slot the slot in the shutdown hook array, whose element - * will be invoked in order during shutdown - * @params registerShutdownInProgress true to allow the hook - * to be registered even if the shutdown is in progress. - * @params hook the hook to be registered - * - * @throw IllegalStateException - * if registerShutdownInProgress is false and shutdown is in progress; or - * if registerShutdownInProgress is true and the shutdown process - * already passes the given slot - */ - static void add(int slot, boolean registerShutdownInProgress, Runnable hook) { - synchronized (lock) { - if (hooks[slot] != null) - throw new InternalError("Shutdown hook at slot " + slot + " already registered"); - - if (!registerShutdownInProgress) { - if (state > RUNNING) - throw new IllegalStateException("Shutdown in progress"); - } else { - if (state > HOOKS || (state == HOOKS && slot <= currentRunningHook)) - throw new IllegalStateException("Shutdown in progress"); - } - - if (!registeredProcessExit) { - registeredProcessExit = true; - registerProcessExit(); - } - - hooks[slot] = hook; - } - } - - /* Run all registered shutdown hooks - */ - private static void runHooks() { - for (int i=0; i < MAX_SYSTEM_HOOKS; i++) { - try { - Runnable hook; - synchronized (lock) { - // acquire the lock to make sure the hook registered during - // shutdown is visible here. - currentRunningHook = i; - hook = hooks[i]; - } - if (hook != null) hook.run(); - } catch(Throwable t) { - if (t instanceof ThreadDeath) { - ThreadDeath td = (ThreadDeath)t; - throw td; - } - } - } - } - - /* The halt method is synchronized on the halt lock - * to avoid corruption of the delete-on-shutdown file list. - * It invokes the true native halt method. - */ - static void halt(int status) { - synchronized (haltLock) { - halt0(status); - } - } - - static void halt0(int status) { - cli.System.Environment.Exit(status); - } - - /* Wormhole for invoking java.lang.ref.Finalizer.runAllFinalizers */ - private static void runAllFinalizers() { /* [IKVM] Don't need to do anything here */ } - - - /* The actual shutdown sequence is defined here. - * - * If it weren't for runFinalizersOnExit, this would be simple -- we'd just - * run the hooks and then halt. Instead we need to keep track of whether - * we're running hooks or finalizers. In the latter case a finalizer could - * invoke exit(1) to cause immediate termination, while in the former case - * any further invocations of exit(n), for any n, simply stall. Note that - * if on-exit finalizers are enabled they're run iff the shutdown is - * initiated by an exit(0); they're never run on exit(n) for n != 0 or in - * response to SIGINT, SIGTERM, etc. - */ - private static void sequence() { - synchronized (lock) { - /* Guard against the possibility of a daemon thread invoking exit - * after DestroyJavaVM initiates the shutdown sequence - */ - if (state != HOOKS) return; - } - runHooks(); - boolean rfoe; - synchronized (lock) { - state = FINALIZERS; - rfoe = runFinalizersOnExit; - } - if (rfoe) runAllFinalizers(); - } - - - /* Invoked by Runtime.exit, which does all the security checks. - * Also invoked by handlers for system-provided termination events, - * which should pass a nonzero status code. - */ - static void exit(int status) { - boolean runMoreFinalizers = false; - synchronized (lock) { - if (status != 0) runFinalizersOnExit = false; - switch (state) { - case RUNNING: /* Initiate shutdown */ - state = HOOKS; - break; - case HOOKS: /* Stall and halt */ - break; - case FINALIZERS: - if (status != 0) { - /* Halt immediately on nonzero status */ - halt(status); - } else { - /* Compatibility with old behavior: - * Run more finalizers and then halt - */ - runMoreFinalizers = runFinalizersOnExit; - } - break; - } - } - if (runMoreFinalizers) { - runAllFinalizers(); - halt(status); - } - synchronized (Shutdown.class) { - /* Synchronize on the class object, causing any other thread - * that attempts to initiate shutdown to stall indefinitely - */ - sequence(); - halt(status); - } - } - - - /* Invoked by the JNI DestroyJavaVM procedure when the last non-daemon - * thread has finished. Unlike the exit method, this method does not - * actually halt the VM. - */ - static void shutdown() { - synchronized (lock) { - switch (state) { - case RUNNING: /* Initiate shutdown */ - state = HOOKS; - break; - case HOOKS: /* Stall and then return */ - case FINALIZERS: - break; - } - } - // [IKVM] We don't block here, because we're being called - // from the AppDomain.ProcessExit event and we don't want to - // deadlock with the thread that called exit. - // Note that our JNI DestroyJavaVM implementation doesn't - // call this method. - if (Monitor.TryEnter(Shutdown.class)) { - try { - sequence(); - } finally { - Monitor.Exit(Shutdown.class); - } - } - } - -} diff --git a/openjdk/java/lang/StringHelper.java b/openjdk/java/lang/StringHelper.java deleted file mode 100644 index 98f7816c..00000000 --- a/openjdk/java/lang/StringHelper.java +++ /dev/null @@ -1,2592 +0,0 @@ -/* - * Copyright (c) 1994, 2010, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package java.lang; - -import java.io.ObjectStreamField; -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Formatter; -import java.util.Locale; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; - -/** - * The <code>String</code> class represents character strings. All - * string literals in Java programs, such as <code>"abc"</code>, are - * implemented as instances of this class. - * <p> - * Strings are constant; their values cannot be changed after they - * are created. String buffers support mutable strings. - * Because String objects are immutable they can be shared. For example: - * <p><blockquote><pre> - * String str = "abc"; - * </pre></blockquote><p> - * is equivalent to: - * <p><blockquote><pre> - * char data[] = {'a', 'b', 'c'}; - * String str = new String(data); - * </pre></blockquote><p> - * Here are some more examples of how strings can be used: - * <p><blockquote><pre> - * System.out.println("abc"); - * String cde = "cde"; - * System.out.println("abc" + cde); - * String c = "abc".substring(2,3); - * String d = cde.substring(1, 2); - * </pre></blockquote> - * <p> - * The class <code>String</code> includes methods for examining - * individual characters of the sequence, for comparing strings, for - * searching strings, for extracting substrings, and for creating a - * copy of a string with all characters translated to uppercase or to - * lowercase. Case mapping is based on the Unicode Standard version - * specified by the {@link java.lang.Character Character} class. - * <p> - * The Java language provides special support for the string - * concatenation operator ( + ), and for conversion of - * other objects to strings. String concatenation is implemented - * through the <code>StringBuilder</code>(or <code>StringBuffer</code>) - * class and its <code>append</code> method. - * String conversions are implemented through the method - * <code>toString</code>, defined by <code>Object</code> and - * inherited by all classes in Java. For additional information on - * string concatenation and conversion, see Gosling, Joy, and Steele, - * <i>The Java Language Specification</i>. - * - * <p> Unless otherwise noted, passing a <tt>null</tt> argument to a constructor - * or method in this class will cause a {@link NullPointerException} to be - * thrown. - * - * <p>A <code>String</code> represents a string in the UTF-16 format - * in which <em>supplementary characters</em> are represented by <em>surrogate - * pairs</em> (see the section <a href="Character.html#unicode">Unicode - * Character Representations</a> in the <code>Character</code> class for - * more information). - * Index values refer to <code>char</code> code units, so a supplementary - * character uses two positions in a <code>String</code>. - * <p>The <code>String</code> class provides methods for dealing with - * Unicode code points (i.e., characters), in addition to those for - * dealing with Unicode code units (i.e., <code>char</code> values). - * - * @author Lee Boynton - * @author Arthur van Hoff - * @author Martin Buchholz - * @author Ulf Zibis - * @see java.lang.Object#toString() - * @see java.lang.StringBuffer - * @see java.lang.StringBuilder - * @see java.nio.charset.Charset - * @since JDK1.0 - */ - -final class StringHelper -{ - /** - * Allocates a new {@code String} that contains characters from a subarray - * of the <a href="Character.html#unicode">Unicode code point</a> array - * argument. The {@code offset} argument is the index of the first code - * point of the subarray and the {@code count} argument specifies the - * length of the subarray. The contents of the subarray are converted to - * {@code char}s; subsequent modification of the {@code int} array does not - * affect the newly created string. - * - * @param codePoints - * Array that is the source of Unicode code points - * - * @param offset - * The initial offset - * - * @param count - * The length - * - * @throws IllegalArgumentException - * If any invalid Unicode code point is found in {@code - * codePoints} - * - * @throws IndexOutOfBoundsException - * If the {@code offset} and {@code count} arguments index - * characters outside the bounds of the {@code codePoints} array - * - * @since 1.5 - */ - static String NewString(int[] codePoints, int offset, int count) { - if (offset < 0) { - throw new StringIndexOutOfBoundsException(offset); - } - if (count < 0) { - throw new StringIndexOutOfBoundsException(count); - } - // Note: offset or count might be near -1>>>1. - if (offset > codePoints.length - count) { - throw new StringIndexOutOfBoundsException(offset + count); - } - - final int end = offset + count; - - // Pass 1: Compute precise size of char[] - int n = count; - for (int i = offset; i < end; i++) { - int c = codePoints[i]; - if (Character.isBmpCodePoint(c)) - continue; - else if (Character.isValidCodePoint(c)) - n++; - else throw new IllegalArgumentException(Integer.toString(c)); - } - - // Pass 2: Allocate and fill in char[] - final char[] v = new char[n]; - - for (int i = offset, j = 0; i < end; i++, j++) { - int c = codePoints[i]; - if (Character.isBmpCodePoint(c)) - v[j] = (char)c; - else - Character.toSurrogates(c, v, j++); - } - - return new String(v); - } - - /** - * Allocates a new {@code String} constructed from a subarray of an array - * of 8-bit integer values. - * - * <p> The {@code offset} argument is the index of the first byte of the - * subarray, and the {@code count} argument specifies the length of the - * subarray. - * - * <p> Each {@code byte} in the subarray is converted to a {@code char} as - * specified in the method above. - * - * @deprecated This method does not properly convert bytes into characters. - * As of JDK 1.1, the preferred way to do this is via the - * {@code String} constructors that take a {@link - * java.nio.charset.Charset}, charset name, or that use the platform's - * default charset. - * - * @param ascii - * The bytes to be converted to characters - * - * @param hibyte - * The top 8 bits of each 16-bit Unicode code unit - * - * @param offset - * The initial offset - * @param count - * The length - * - * @throws IndexOutOfBoundsException - * If the {@code offset} or {@code count} argument is invalid - * - * @see #String(byte[], int) - * @see #String(byte[], int, int, java.lang.String) - * @see #String(byte[], int, int, java.nio.charset.Charset) - * @see #String(byte[], int, int) - * @see #String(byte[], java.lang.String) - * @see #String(byte[], java.nio.charset.Charset) - * @see #String(byte[]) - */ - @Deprecated - static String NewString(byte ascii[], int hibyte, int offset, int count) { - checkBounds(ascii, offset, count); - char value[] = new char[count]; - - if (hibyte == 0) { - for (int i = count; i-- > 0;) { - value[i] = (char)(ascii[i + offset] & 0xff); - } - } else { - hibyte <<= 8; - for (int i = count; i-- > 0;) { - value[i] = (char)(hibyte | (ascii[i + offset] & 0xff)); - } - } - return new String(value, 0, count); - } - - /** - * Allocates a new {@code String} containing characters constructed from - * an array of 8-bit integer values. Each character <i>c</i>in the - * resulting string is constructed from the corresponding component - * <i>b</i> in the byte array such that: - * - * <blockquote><pre> - * <b><i>c</i></b> == (char)(((hibyte & 0xff) << 8) - * | (<b><i>b</i></b> & 0xff)) - * </pre></blockquote> - * - * @deprecated This method does not properly convert bytes into - * characters. As of JDK 1.1, the preferred way to do this is via the - * {@code String} constructors that take a {@link - * java.nio.charset.Charset}, charset name, or that use the platform's - * default charset. - * - * @param ascii - * The bytes to be converted to characters - * - * @param hibyte - * The top 8 bits of each 16-bit Unicode code unit - * - * @see #String(byte[], int, int, java.lang.String) - * @see #String(byte[], int, int, java.nio.charset.Charset) - * @see #String(byte[], int, int) - * @see #String(byte[], java.lang.String) - * @see #String(byte[], java.nio.charset.Charset) - * @see #String(byte[]) - */ - @Deprecated - static String NewString(byte ascii[], int hibyte) { - return NewString(ascii, hibyte, 0, ascii.length); - } - - /* Common private utility method used to bounds check the byte array - * and requested offset & length values used by the String(byte[],..) - * constructors. - */ - private static void checkBounds(byte[] bytes, int offset, int length) { - if (length < 0) - throw new StringIndexOutOfBoundsException(length); - if (offset < 0) - throw new StringIndexOutOfBoundsException(offset); - if (offset > bytes.length - length) - throw new StringIndexOutOfBoundsException(offset + length); - } - - /** - * Constructs a new {@code String} by decoding the specified subarray of - * bytes using the specified charset. The length of the new {@code String} - * is a function of the charset, and hence may not be equal to the length - * of the subarray. - * - * <p> The behavior of this constructor when the given bytes are not valid - * in the given charset is unspecified. The {@link - * java.nio.charset.CharsetDecoder} class should be used when more control - * over the decoding process is required. - * - * @param bytes - * The bytes to be decoded into characters - * - * @param offset - * The index of the first byte to decode - * - * @param length - * The number of bytes to decode - - * @param charsetName - * The name of a supported {@linkplain java.nio.charset.Charset - * charset} - * - * @throws UnsupportedEncodingException - * If the named charset is not supported - * - * @throws IndexOutOfBoundsException - * If the {@code offset} and {@code length} arguments index - * characters outside the bounds of the {@code bytes} array - * - * @since JDK1.1 - */ - static String NewString(byte bytes[], int offset, int length, String charsetName) - throws UnsupportedEncodingException { - if (charsetName == null) - throw new NullPointerException("charsetName"); - checkBounds(bytes, offset, length); - char[] v = StringCoding.decode(charsetName, bytes, offset, length); - return new String(v); - } - - /** - * Constructs a new {@code String} by decoding the specified subarray of - * bytes using the specified {@linkplain java.nio.charset.Charset charset}. - * The length of the new {@code String} is a function of the charset, and - * hence may not be equal to the length of the subarray. - * - * <p> This method always replaces malformed-input and unmappable-character - * sequences with this charset's default replacement string. The {@link - * java.nio.charset.CharsetDecoder} class should be used when more control - * over the decoding process is required. - * - * @param bytes - * The bytes to be decoded into characters - * - * @param offset - * The index of the first byte to decode - * - * @param length - * The number of bytes to decode - * - * @param charset - * The {@linkplain java.nio.charset.Charset charset} to be used to - * decode the {@code bytes} - * - * @throws IndexOutOfBoundsException - * If the {@code offset} and {@code length} arguments index - * characters outside the bounds of the {@code bytes} array - * - * @since 1.6 - */ - static String NewString(byte bytes[], int offset, int length, Charset charset) { - if (charset == null) - throw new NullPointerException("charset"); - checkBounds(bytes, offset, length); - char[] v = StringCoding.decode(charset, bytes, offset, length); - return new String(v); - } - - /** - * Constructs a new {@code String} by decoding the specified array of bytes - * using the specified {@linkplain java.nio.charset.Charset charset}. The - * length of the new {@code String} is a function of the charset, and hence - * may not be equal to the length of the byte array. - * - * <p> The behavior of this constructor when the given bytes are not valid - * in the given charset is unspecified. The {@link - * java.nio.charset.CharsetDecoder} class should be used when more control - * over the decoding process is required. - * - * @param bytes - * The bytes to be decoded into characters - * - * @param charsetName - * The name of a supported {@linkplain java.nio.charset.Charset - * charset} - * - * @throws UnsupportedEncodingException - * If the named charset is not supported - * - * @since JDK1.1 - */ - static String NewString(byte bytes[], String charsetName) - throws UnsupportedEncodingException { - return NewString(bytes, 0, bytes.length, charsetName); - } - - /** - * Constructs a new {@code String} by decoding the specified array of - * bytes using the specified {@linkplain java.nio.charset.Charset charset}. - * The length of the new {@code String} is a function of the charset, and - * hence may not be equal to the length of the byte array. - * - * <p> This method always replaces malformed-input and unmappable-character - * sequences with this charset's default replacement string. The {@link - * java.nio.charset.CharsetDecoder} class should be used when more control - * over the decoding process is required. - * - * @param bytes - * The bytes to be decoded into characters - * - * @param charset - * The {@linkplain java.nio.charset.Charset charset} to be used to - * decode the {@code bytes} - * - * @since 1.6 - */ - static String NewString(byte bytes[], Charset charset) { - return NewString(bytes, 0, bytes.length, charset); - } - - /** - * Constructs a new {@code String} by decoding the specified subarray of - * bytes using the platform's default charset. The length of the new - * {@code String} is a function of the charset, and hence may not be equal - * to the length of the subarray. - * - * <p> The behavior of this constructor when the given bytes are not valid - * in the default charset is unspecified. The {@link - * java.nio.charset.CharsetDecoder} class should be used when more control - * over the decoding process is required. - * - * @param bytes - * The bytes to be decoded into characters - * - * @param offset - * The index of the first byte to decode - * - * @param length - * The number of bytes to decode - * - * @throws IndexOutOfBoundsException - * If the {@code offset} and the {@code length} arguments index - * characters outside the bounds of the {@code bytes} array - * - * @since JDK1.1 - */ - static String NewString(byte bytes[], int offset, int length) { - checkBounds(bytes, offset, length); - char[] v = StringCoding.decode(bytes, offset, length); - return new String(v); - } - - /** - * Constructs a new {@code String} by decoding the specified array of bytes - * using the platform's default charset. The length of the new {@code - * String} is a function of the charset, and hence may not be equal to the - * length of the byte array. - * - * <p> The behavior of this constructor when the given bytes are not valid - * in the default charset is unspecified. The {@link - * java.nio.charset.CharsetDecoder} class should be used when more control - * over the decoding process is required. - * - * @param bytes - * The bytes to be decoded into characters - * - * @since JDK1.1 - */ - static String NewString(byte bytes[]) { - return NewString(bytes, 0, bytes.length); - } - - /** - * Allocates a new string that contains the sequence of characters - * currently contained in the string buffer argument. The contents of the - * string buffer are copied; subsequent modification of the string buffer - * does not affect the newly created string. - * - * @param buffer - * A {@code StringBuffer} - */ - static String NewString(StringBuffer buffer) { - return buffer.toString(); - } - - /** - * Allocates a new string that contains the sequence of characters - * currently contained in the string builder argument. The contents of the - * string builder are copied; subsequent modification of the string builder - * does not affect the newly created string. - * - * <p> This constructor is provided to ease migration to {@code - * StringBuilder}. Obtaining a string from a string builder via the {@code - * toString} method is likely to run faster and is generally preferred. - * - * @param builder - * A {@code StringBuilder} - * - * @since 1.5 - */ - static String NewString(StringBuilder builder) { - return builder.toString(); - } - - - // Package private constructor which shares value array for speed. - static String NewString(int offset, int count, char value[]) { - return new String(value, offset, count); - } - - /** - * Returns the character (Unicode code point) at the specified - * index. The index refers to <code>char</code> values - * (Unicode code units) and ranges from <code>0</code> to - * {@link #length()}<code> - 1</code>. - * - * <p> If the <code>char</code> value specified at the given index - * is in the high-surrogate range, the following index is less - * than the length of this <code>String</code>, and the - * <code>char</code> value at the following index is in the - * low-surrogate range, then the supplementary code point - * corresponding to this surrogate pair is returned. Otherwise, - * the <code>char</code> value at the given index is returned. - * - * @param index the index to the <code>char</code> values - * @return the code point value of the character at the - * <code>index</code> - * @exception IndexOutOfBoundsException if the <code>index</code> - * argument is negative or not less than the length of this - * string. - * @since 1.5 - */ - static int codePointAt(String _this, int index) { - if ((index < 0) || (index >= _this.length())) { - throw new StringIndexOutOfBoundsException(index); - } - char c1 = _this.charAt(index++); - if (Character.isHighSurrogate(c1)) { - if (index < _this.length()) { - char c2 = _this.charAt(index); - if (Character.isLowSurrogate(c2)) { - return Character.toCodePoint(c1, c2); - } - } - } - return c1; - } - - /** - * Returns the character (Unicode code point) before the specified - * index. The index refers to <code>char</code> values - * (Unicode code units) and ranges from <code>1</code> to {@link - * CharSequence#length() length}. - * - * <p> If the <code>char</code> value at <code>(index - 1)</code> - * is in the low-surrogate range, <code>(index - 2)</code> is not - * negative, and the <code>char</code> value at <code>(index - - * 2)</code> is in the high-surrogate range, then the - * supplementary code point value of the surrogate pair is - * returned. If the <code>char</code> value at <code>index - - * 1</code> is an unpaired low-surrogate or a high-surrogate, the - * surrogate value is returned. - * - * @param index the index following the code point that should be returned - * @return the Unicode code point value before the given index. - * @exception IndexOutOfBoundsException if the <code>index</code> - * argument is less than 1 or greater than the length - * of this string. - * @since 1.5 - */ - static int codePointBefore(String _this, int index) { - int i = index - 1; - if ((i < 0) || (i >= _this.length())) { - throw new StringIndexOutOfBoundsException(index); - } - char c2 = _this.charAt(--index); - if (Character.isLowSurrogate(c2)) { - if (index > 0) { - char c1 = _this.charAt(--index); - if (Character.isHighSurrogate(c1)) { - return Character.toCodePoint(c1, c2); - } - } - } - return c2; - } - - /** - * Returns the number of Unicode code points in the specified text - * range of this <code>String</code>. The text range begins at the - * specified <code>beginIndex</code> and extends to the - * <code>char</code> at index <code>endIndex - 1</code>. Thus the - * length (in <code>char</code>s) of the text range is - * <code>endIndex-beginIndex</code>. Unpaired surrogates within - * the text range count as one code point each. - * - * @param beginIndex the index to the first <code>char</code> of - * the text range. - * @param endIndex the index after the last <code>char</code> of - * the text range. - * @return the number of Unicode code points in the specified text - * range - * @exception IndexOutOfBoundsException if the - * <code>beginIndex</code> is negative, or <code>endIndex</code> - * is larger than the length of this <code>String</code>, or - * <code>beginIndex</code> is larger than <code>endIndex</code>. - * @since 1.5 - */ - static int codePointCount(String _this, int beginIndex, int endIndex) { - if (beginIndex < 0 || endIndex > _this.length() || beginIndex > endIndex) { - throw new IndexOutOfBoundsException(); - } - int n = 0; - for (int i = beginIndex; i < endIndex; ) { - n++; - if (Character.isHighSurrogate(_this.charAt(i++))) { - if (i < endIndex && Character.isLowSurrogate(_this.charAt(i))) { - i++; - } - } - } - return n; - } - - /** - * Returns the index within this <code>String</code> that is - * offset from the given <code>index</code> by - * <code>codePointOffset</code> code points. Unpaired surrogates - * within the text range given by <code>index</code> and - * <code>codePointOffset</code> count as one code point each. - * - * @param index the index to be offset - * @param codePointOffset the offset in code points - * @return the index within this <code>String</code> - * @exception IndexOutOfBoundsException if <code>index</code> - * is negative or larger then the length of this - * <code>String</code>, or if <code>codePointOffset</code> is positive - * and the substring starting with <code>index</code> has fewer - * than <code>codePointOffset</code> code points, - * or if <code>codePointOffset</code> is negative and the substring - * before <code>index</code> has fewer than the absolute value - * of <code>codePointOffset</code> code points. - * @since 1.5 - */ - static int offsetByCodePoints(String _this, int index, int codePointOffset) { - int count = _this.length(); - if (index < 0 || index > count) { - throw new IndexOutOfBoundsException(); - } - int x = index; - if (codePointOffset >= 0) { - int limit = count; - int i; - for (i = 0; x < limit && i < codePointOffset; i++) { - if (Character.isHighSurrogate(_this.charAt(x++))) { - if (x < limit && Character.isLowSurrogate(_this.charAt(x))) { - x++; - } - } - } - if (i < codePointOffset) { - throw new IndexOutOfBoundsException(); - } - } else { - int i; - for (i = codePointOffset; x > 0 && i < 0; i++) { - if (Character.isLowSurrogate(_this.charAt(--x))) { - if (x > 0 && Character.isHighSurrogate(_this.charAt(x-1))) { - x--; - } - } - } - if (i < 0) { - throw new IndexOutOfBoundsException(); - } - } - return x; - } - - /** - * Copy characters from this string into dst starting at dstBegin. - * This method doesn't perform any range checking. - */ - static void getChars(String _this, char dst[], int dstBegin) { - _this.getChars(0, _this.length(), dst, dstBegin); - } - - /** - * Copies characters from this string into the destination character - * array. - * <p> - * The first character to be copied is at index <code>srcBegin</code>; - * the last character to be copied is at index <code>srcEnd-1</code> - * (thus the total number of characters to be copied is - * <code>srcEnd-srcBegin</code>). The characters are copied into the - * subarray of <code>dst</code> starting at index <code>dstBegin</code> - * and ending at index: - * <p><blockquote><pre> - * dstbegin + (srcEnd-srcBegin) - 1 - * </pre></blockquote> - * - * @param srcBegin index of the first character in the string - * to copy. - * @param srcEnd index after the last character in the string - * to copy. - * @param dst the destination array. - * @param dstBegin the start offset in the destination array. - * @exception IndexOutOfBoundsException If any of the following - * is true: - * <ul><li><code>srcBegin</code> is negative. - * <li><code>srcBegin</code> is greater than <code>srcEnd</code> - * <li><code>srcEnd</code> is greater than the length of this - * string - * <li><code>dstBegin</code> is negative - * <li><code>dstBegin+(srcEnd-srcBegin)</code> is larger than - * <code>dst.length</code></ul> - */ - static void getChars(cli.System.String _this, int srcBegin, int srcEnd, char dst[], int dstBegin) { - if (srcBegin < 0) { - throw new StringIndexOutOfBoundsException(srcBegin); - } - if (srcEnd > _this.get_Length()) { - throw new StringIndexOutOfBoundsException(srcEnd); - } - if (srcBegin > srcEnd) { - throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); - } - _this.CopyTo(srcBegin, dst, dstBegin, srcEnd - srcBegin); - } - - /** - * Copies characters from this string into the destination byte array. Each - * byte receives the 8 low-order bits of the corresponding character. The - * eight high-order bits of each character are not copied and do not - * participate in the transfer in any way. - * - * <p> The first character to be copied is at index {@code srcBegin}; the - * last character to be copied is at index {@code srcEnd-1}. The total - * number of characters to be copied is {@code srcEnd-srcBegin}. The - * characters, converted to bytes, are copied into the subarray of {@code - * dst} starting at index {@code dstBegin} and ending at index: - * - * <blockquote><pre> - * dstbegin + (srcEnd-srcBegin) - 1 - * </pre></blockquote> - * - * @deprecated This method does not properly convert characters into - * bytes. As of JDK 1.1, the preferred way to do this is via the - * {@link #getBytes()} method, which uses the platform's default charset. - * - * @param srcBegin - * Index of the first character in the string to copy - * - * @param srcEnd - * Index after the last character in the string to copy - * - * @param dst - * The destination array - * - * @param dstBegin - * The start offset in the destination array - * - * @throws IndexOutOfBoundsException - * If any of the following is true: - * <ul> - * <li> {@code srcBegin} is negative - * <li> {@code srcBegin} is greater than {@code srcEnd} - * <li> {@code srcEnd} is greater than the length of this String - * <li> {@code dstBegin} is negative - * <li> {@code dstBegin+(srcEnd-srcBegin)} is larger than {@code - * dst.length} - * </ul> - */ - @Deprecated - static void getBytes(String _this, int srcBegin, int srcEnd, byte dst[], int dstBegin) { - if (srcBegin < 0) { - throw new StringIndexOutOfBoundsException(srcBegin); - } - if (srcEnd > _this.length()) { - throw new StringIndexOutOfBoundsException(srcEnd); - } - if (srcBegin > srcEnd) { - throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); - } - int j = dstBegin; - int n = srcEnd; - int i = srcBegin; - - while (i < n) { - dst[j++] = (byte)_this.charAt(i++); - } - } - - /** - * Encodes this {@code String} into a sequence of bytes using the named - * charset, storing the result into a new byte array. - * - * <p> The behavior of this method when this string cannot be encoded in - * the given charset is unspecified. The {@link - * java.nio.charset.CharsetEncoder} class should be used when more control - * over the encoding process is required. - * - * @param charsetName - * The name of a supported {@linkplain java.nio.charset.Charset - * charset} - * - * @return The resultant byte array - * - * @throws UnsupportedEncodingException - * If the named charset is not supported - * - * @since JDK1.1 - */ - static byte[] getBytes(String _this, String charsetName) - throws UnsupportedEncodingException { - if (charsetName == null) throw new NullPointerException(); - char[] value = _this.toCharArray(); - return StringCoding.encode(charsetName, value, 0, value.length); - } - - /** - * Encodes this {@code String} into a sequence of bytes using the given - * {@linkplain java.nio.charset.Charset charset}, storing the result into a - * new byte array. - * - * <p> This method always replaces malformed-input and unmappable-character - * sequences with this charset's default replacement byte array. The - * {@link java.nio.charset.CharsetEncoder} class should be used when more - * control over the encoding process is required. - * - * @param charset - * The {@linkplain java.nio.charset.Charset} to be used to encode - * the {@code String} - * - * @return The resultant byte array - * - * @since 1.6 - */ - static byte[] getBytes(String _this, Charset charset) { - if (charset == null) throw new NullPointerException(); - char[] value = _this.toCharArray(); - return StringCoding.encode(charset, value, 0, value.length); - } - - /** - * Encodes this {@code String} into a sequence of bytes using the - * platform's default charset, storing the result into a new byte array. - * - * <p> The behavior of this method when this string cannot be encoded in - * the default charset is unspecified. The {@link - * java.nio.charset.CharsetEncoder} class should be used when more control - * over the encoding process is required. - * - * @return The resultant byte array - * - * @since JDK1.1 - */ - static byte[] getBytes(String _this) { - char[] value = _this.toCharArray(); - return StringCoding.encode(value, 0, value.length); - } - - /** - * Compares this string to the specified {@code StringBuffer}. The result - * is {@code true} if and only if this {@code String} represents the same - * sequence of characters as the specified {@code StringBuffer}. - * - * @param sb - * The {@code StringBuffer} to compare this {@code String} against - * - * @return {@code true} if this {@code String} represents the same - * sequence of characters as the specified {@code StringBuffer}, - * {@code false} otherwise - * - * @since 1.4 - */ - static boolean contentEquals(String _this, StringBuffer sb) { - synchronized (sb) { - return contentEquals(_this, (CharSequence) sb); - } - } - - /** - * Compares this string to the specified {@code CharSequence}. The result - * is {@code true} if and only if this {@code String} represents the same - * sequence of char values as the specified sequence. - * - * @param cs - * The sequence to compare this {@code String} against - * - * @return {@code true} if this {@code String} represents the same - * sequence of char values as the specified sequence, {@code - * false} otherwise - * - * @since 1.5 - */ - static boolean contentEquals(String _this, CharSequence cs) { - if (_this.length() != cs.length()) - return false; - // Argument is a StringBuffer, StringBuilder - if (cs instanceof AbstractStringBuilder) { - char v2[] = ((AbstractStringBuilder) cs).getValue(); - int i = 0; - int n = _this.length(); - while (n-- != 0) { - if (_this.charAt(i) != v2[i]) - return false; - i++; - } - return true; - } - // Argument is a String - if (cs.equals(_this)) - return true; - // Argument is a generic CharSequence - int i = 0; - int n = _this.length(); - while (n-- != 0) { - if (_this.charAt(i) != cs.charAt(i)) - return false; - i++; - } - return true; - } - - /** - * Compares this {@code String} to another {@code String}, ignoring case - * considerations. Two strings are considered equal ignoring case if they - * are of the same length and corresponding characters in the two strings - * are equal ignoring case. - * - * <p> Two characters {@code c1} and {@code c2} are considered the same - * ignoring case if at least one of the following is true: - * <ul> - * <li> The two characters are the same (as compared by the - * {@code ==} operator) - * <li> Applying the method {@link - * java.lang.Character#toUpperCase(char)} to each character - * produces the same result - * <li> Applying the method {@link - * java.lang.Character#toLowerCase(char)} to each character - * produces the same result - * </ul> - * - * @param anotherString - * The {@code String} to compare this {@code String} against - * - * @return {@code true} if the argument is not {@code null} and it - * represents an equivalent {@code String} ignoring case; {@code - * false} otherwise - * - * @see #equals(Object) - */ - static boolean equalsIgnoreCase(String _this, String anotherString) { - return (_this == anotherString) ? true - : (anotherString != null) - && (anotherString.length() == _this.length()) - && regionMatches(_this, true, 0, anotherString, 0, _this.length()); - } - - /** - * Compares two strings lexicographically. - * The comparison is based on the Unicode value of each character in - * the strings. The character sequence represented by this - * <code>String</code> object is compared lexicographically to the - * character sequence represented by the argument string. The result is - * a negative integer if this <code>String</code> object - * lexicographically precedes the argument string. The result is a - * positive integer if this <code>String</code> object lexicographically - * follows the argument string. The result is zero if the strings - * are equal; <code>compareTo</code> returns <code>0</code> exactly when - * the {@link #equals(Object)} method would return <code>true</code>. - * <p> - * This is the definition of lexicographic ordering. If two strings are - * different, then either they have different characters at some index - * that is a valid index for both strings, or their lengths are different, - * or both. If they have different characters at one or more index - * positions, let <i>k</i> be the smallest such index; then the string - * whose character at position <i>k</i> has the smaller value, as - * determined by using the < operator, lexicographically precedes the - * other string. In this case, <code>compareTo</code> returns the - * difference of the two character values at position <code>k</code> in - * the two string -- that is, the value: - * <blockquote><pre> - * this.charAt(k)-anotherString.charAt(k) - * </pre></blockquote> - * If there is no index position at which they differ, then the shorter - * string lexicographically precedes the longer string. In this case, - * <code>compareTo</code> returns the difference of the lengths of the - * strings -- that is, the value: - * <blockquote><pre> - * this.length()-anotherString.length() - * </pre></blockquote> - * - * @param anotherString the <code>String</code> to be compared. - * @return the value <code>0</code> if the argument string is equal to - * this string; a value less than <code>0</code> if this string - * is lexicographically less than the string argument; and a - * value greater than <code>0</code> if this string is - * lexicographically greater than the string argument. - */ - static int compareTo(String _this, String anotherString) { - int len = Math.min(_this.length(), anotherString.length()); - for (int i = 0; i < len; i++) - { - int diff = _this.charAt(i) - anotherString.charAt(i); - if (diff != 0) - { - return diff; - } - } - return _this.length() - anotherString.length(); - } - - /** - * Compares two strings lexicographically, ignoring case - * differences. This method returns an integer whose sign is that of - * calling <code>compareTo</code> with normalized versions of the strings - * where case differences have been eliminated by calling - * <code>Character.toLowerCase(Character.toUpperCase(character))</code> on - * each character. - * <p> - * Note that this method does <em>not</em> take locale into account, - * and will result in an unsatisfactory ordering for certain locales. - * The java.text package provides <em>collators</em> to allow - * locale-sensitive ordering. - * - * @param str the <code>String</code> to be compared. - * @return a negative integer, zero, or a positive integer as the - * specified String is greater than, equal to, or less - * than this String, ignoring case considerations. - * @see java.text.Collator#compare(String, String) - * @since 1.2 - */ - static int compareToIgnoreCase(String _this, String str) { - return String.CASE_INSENSITIVE_ORDER.compare(_this, str); - } - - /** - * Tests if two string regions are equal. - * <p> - * A substring of this <tt>String</tt> object is compared to a substring - * of the argument other. The result is true if these substrings - * represent identical character sequences. The substring of this - * <tt>String</tt> object to be compared begins at index <tt>toffset</tt> - * and has length <tt>len</tt>. The substring of other to be compared - * begins at index <tt>ooffset</tt> and has length <tt>len</tt>. The - * result is <tt>false</tt> if and only if at least one of the following - * is true: - * <ul><li><tt>toffset</tt> is negative. - * <li><tt>ooffset</tt> is negative. - * <li><tt>toffset+len</tt> is greater than the length of this - * <tt>String</tt> object. - * <li><tt>ooffset+len</tt> is greater than the length of the other - * argument. - * <li>There is some nonnegative integer <i>k</i> less than <tt>len</tt> - * such that: - * <tt>this.charAt(toffset+<i>k</i>) != other.charAt(ooffset+<i>k</i>)</tt> - * </ul> - * - * @param toffset the starting offset of the subregion in this string. - * @param other the string argument. - * @param ooffset the starting offset of the subregion in the string - * argument. - * @param len the number of characters to compare. - * @return <code>true</code> if the specified subregion of this string - * exactly matches the specified subregion of the string argument; - * <code>false</code> otherwise. - */ - static boolean regionMatches(String _this, int toffset, String other, int ooffset, - int len) { - int to = toffset; - int po = ooffset; - // Note: toffset, ooffset, or len might be near -1>>>1. - if ((ooffset < 0) || (toffset < 0) - || (toffset > (long)_this.length() - len) - || (ooffset > (long)other.length() - len)) { - return false; - } - while (len-- > 0) { - if (_this.charAt(to++) != other.charAt(po++)) { - return false; - } - } - return true; - } - - /** - * Tests if two string regions are equal. - * <p> - * A substring of this <tt>String</tt> object is compared to a substring - * of the argument <tt>other</tt>. The result is <tt>true</tt> if these - * substrings represent character sequences that are the same, ignoring - * case if and only if <tt>ignoreCase</tt> is true. The substring of - * this <tt>String</tt> object to be compared begins at index - * <tt>toffset</tt> and has length <tt>len</tt>. The substring of - * <tt>other</tt> to be compared begins at index <tt>ooffset</tt> and - * has length <tt>len</tt>. The result is <tt>false</tt> if and only if - * at least one of the following is true: - * <ul><li><tt>toffset</tt> is negative. - * <li><tt>ooffset</tt> is negative. - * <li><tt>toffset+len</tt> is greater than the length of this - * <tt>String</tt> object. - * <li><tt>ooffset+len</tt> is greater than the length of the other - * argument. - * <li><tt>ignoreCase</tt> is <tt>false</tt> and there is some nonnegative - * integer <i>k</i> less than <tt>len</tt> such that: - * <blockquote><pre> - * this.charAt(toffset+k) != other.charAt(ooffset+k) - * </pre></blockquote> - * <li><tt>ignoreCase</tt> is <tt>true</tt> and there is some nonnegative - * integer <i>k</i> less than <tt>len</tt> such that: - * <blockquote><pre> - * Character.toLowerCase(this.charAt(toffset+k)) != - Character.toLowerCase(other.charAt(ooffset+k)) - * </pre></blockquote> - * and: - * <blockquote><pre> - * Character.toUpperCase(this.charAt(toffset+k)) != - * Character.toUpperCase(other.charAt(ooffset+k)) - * </pre></blockquote> - * </ul> - * - * @param ignoreCase if <code>true</code>, ignore case when comparing - * characters. - * @param toffset the starting offset of the subregion in this - * string. - * @param other the string argument. - * @param ooffset the starting offset of the subregion in the string - * argument. - * @param len the number of characters to compare. - * @return <code>true</code> if the specified subregion of this string - * matches the specified subregion of the string argument; - * <code>false</code> otherwise. Whether the matching is exact - * or case insensitive depends on the <code>ignoreCase</code> - * argument. - */ - static boolean regionMatches(String _this, boolean ignoreCase, int toffset, - String other, int ooffset, int len) { - int to = toffset; - int po = ooffset; - // Note: toffset, ooffset, or len might be near -1>>>1. - if ((ooffset < 0) || (toffset < 0) - || (toffset > (long)_this.length() - len) - || (ooffset > (long)other.length() - len)) { - return false; - } - while (len-- > 0) { - char c1 = _this.charAt(to++); - char c2 = other.charAt(po++); - if (c1 == c2) { - continue; - } - if (ignoreCase) { - // If characters don't match but case may be ignored, - // try converting both characters to uppercase. - // If the results match, then the comparison scan should - // continue. - char u1 = Character.toUpperCase(c1); - char u2 = Character.toUpperCase(c2); - if (u1 == u2) { - continue; - } - // Unfortunately, conversion to uppercase does not work properly - // for the Georgian alphabet, which has strange rules about case - // conversion. So we need to make one last check before - // exiting. - if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) { - continue; - } - } - return false; - } - return true; - } - - /** - * Returns a hash code for this string. The hash code for a - * <code>String</code> object is computed as - * <blockquote><pre> - * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] - * </pre></blockquote> - * using <code>int</code> arithmetic, where <code>s[i]</code> is the - * <i>i</i>th character of the string, <code>n</code> is the length of - * the string, and <code>^</code> indicates exponentiation. - * (The hash value of the empty string is zero.) - * - * @return a hash code value for this object. - */ - static int hashCode(cli.System.String _this) { - int h = 0; - // NOTE having the get_Length in the for condition is actually faster than hoisting it, - // the CLR JIT recognizes this pattern and optimizes the array bounds check in get_Chars. - for (int i = 0; i < _this.get_Length(); i++) - { - h = h * 31 + _this.get_Chars(i); - } - return h; - } - - /** - * Returns the index within this string of the first occurrence of - * the specified character. If a character with value - * <code>ch</code> occurs in the character sequence represented by - * this <code>String</code> object, then the index (in Unicode - * code units) of the first such occurrence is returned. For - * values of <code>ch</code> in the range from 0 to 0xFFFF - * (inclusive), this is the smallest value <i>k</i> such that: - * <blockquote><pre> - * this.charAt(<i>k</i>) == ch - * </pre></blockquote> - * is true. For other values of <code>ch</code>, it is the - * smallest value <i>k</i> such that: - * <blockquote><pre> - * this.codePointAt(<i>k</i>) == ch - * </pre></blockquote> - * is true. In either case, if no such character occurs in this - * string, then <code>-1</code> is returned. - * - * @param ch a character (Unicode code point). - * @return the index of the first occurrence of the character in the - * character sequence represented by this object, or - * <code>-1</code> if the character does not occur. - */ - static int indexOf(cli.System.String _this, int ch) { - return indexOf(_this, ch, 0); - } - - /** - * Returns the index within this string of the first occurrence of the - * specified character, starting the search at the specified index. - * <p> - * If a character with value <code>ch</code> occurs in the - * character sequence represented by this <code>String</code> - * object at an index no smaller than <code>fromIndex</code>, then - * the index of the first such occurrence is returned. For values - * of <code>ch</code> in the range from 0 to 0xFFFF (inclusive), - * this is the smallest value <i>k</i> such that: - * <blockquote><pre> - * (this.charAt(<i>k</i>) == ch) && (<i>k</i> >= fromIndex) - * </pre></blockquote> - * is true. For other values of <code>ch</code>, it is the - * smallest value <i>k</i> such that: - * <blockquote><pre> - * (this.codePointAt(<i>k</i>) == ch) && (<i>k</i> >= fromIndex) - * </pre></blockquote> - * is true. In either case, if no such character occurs in this - * string at or after position <code>fromIndex</code>, then - * <code>-1</code> is returned. - * - * <p> - * There is no restriction on the value of <code>fromIndex</code>. If it - * is negative, it has the same effect as if it were zero: this entire - * string may be searched. If it is greater than the length of this - * string, it has the same effect as if it were equal to the length of - * this string: <code>-1</code> is returned. - * - * <p>All indices are specified in <code>char</code> values - * (Unicode code units). - * - * @param ch a character (Unicode code point). - * @param fromIndex the index to start the search from. - * @return the index of the first occurrence of the character in the - * character sequence represented by this object that is greater - * than or equal to <code>fromIndex</code>, or <code>-1</code> - * if the character does not occur. - */ - static int indexOf(cli.System.String _this, int ch, int fromIndex) { - int max = _this.get_Length(); - - if (fromIndex < 0) { - fromIndex = 0; - } else if (fromIndex >= max) { - // Note: fromIndex might be near -1>>>1. - return -1; - } - - int i = fromIndex; - if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { - // handle most cases here (ch is a BMP code point or a - // negative value (invalid code point)) - for (; i < max ; i++) { - if (_this.get_Chars(i) == ch) { - return i; - } - } - return -1; - } else { - return indexOfSupplementary(_this, ch, fromIndex); - } - } - - /** - * Handles (rare) calls of indexOf with a supplementary character. - */ - private static int indexOfSupplementary(cli.System.String _this, int ch, int fromIndex) { - if (Character.isValidCodePoint(ch)) { - final char hi = Character.highSurrogate(ch); - final char lo = Character.lowSurrogate(ch); - final int max = _this.get_Length() - 1; - for (int i = fromIndex; i < max; i++) { - if (_this.get_Chars(i) == hi && _this.get_Chars(i+1) == lo) { - return i; - } - } - } - return -1; - } - - /** - * Returns the index within this string of the last occurrence of - * the specified character. For values of <code>ch</code> in the - * range from 0 to 0xFFFF (inclusive), the index (in Unicode code - * units) returned is the largest value <i>k</i> such that: - * <blockquote><pre> - * this.charAt(<i>k</i>) == ch - * </pre></blockquote> - * is true. For other values of <code>ch</code>, it is the - * largest value <i>k</i> such that: - * <blockquote><pre> - * this.codePointAt(<i>k</i>) == ch - * </pre></blockquote> - * is true. In either case, if no such character occurs in this - * string, then <code>-1</code> is returned. The - * <code>String</code> is searched backwards starting at the last - * character. - * - * @param ch a character (Unicode code point). - * @return the index of the last occurrence of the character in the - * character sequence represented by this object, or - * <code>-1</code> if the character does not occur. - */ - static int lastIndexOf(cli.System.String _this, int ch) { - return lastIndexOf(_this, ch, _this.get_Length() - 1); - } - - /** - * Returns the index within this string of the last occurrence of - * the specified character, searching backward starting at the - * specified index. For values of <code>ch</code> in the range - * from 0 to 0xFFFF (inclusive), the index returned is the largest - * value <i>k</i> such that: - * <blockquote><pre> - * (this.charAt(<i>k</i>) == ch) && (<i>k</i> <= fromIndex) - * </pre></blockquote> - * is true. For other values of <code>ch</code>, it is the - * largest value <i>k</i> such that: - * <blockquote><pre> - * (this.codePointAt(<i>k</i>) == ch) && (<i>k</i> <= fromIndex) - * </pre></blockquote> - * is true. In either case, if no such character occurs in this - * string at or before position <code>fromIndex</code>, then - * <code>-1</code> is returned. - * - * <p>All indices are specified in <code>char</code> values - * (Unicode code units). - * - * @param ch a character (Unicode code point). - * @param fromIndex the index to start the search from. There is no - * restriction on the value of <code>fromIndex</code>. If it is - * greater than or equal to the length of this string, it has - * the same effect as if it were equal to one less than the - * length of this string: this entire string may be searched. - * If it is negative, it has the same effect as if it were -1: - * -1 is returned. - * @return the index of the last occurrence of the character in the - * character sequence represented by this object that is less - * than or equal to <code>fromIndex</code>, or <code>-1</code> - * if the character does not occur before that point. - */ - static int lastIndexOf(cli.System.String _this, int ch, int fromIndex) { - if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { - // handle most cases here (ch is a BMP code point or a - // negative value (invalid code point)) - int i = Math.min(fromIndex, _this.get_Length() - 1); - for (; i >= 0; i--) { - if (_this.get_Chars(i) == ch) { - return i; - } - } - return -1; - } else { - return lastIndexOfSupplementary(_this, ch, fromIndex); - } - } - - /** - * Handles (rare) calls of lastIndexOf with a supplementary character. - */ - private static int lastIndexOfSupplementary(cli.System.String _this, int ch, int fromIndex) { - if (Character.isValidCodePoint(ch)) { - char hi = Character.highSurrogate(ch); - char lo = Character.lowSurrogate(ch); - int i = Math.min(fromIndex, _this.get_Length() - 2); - for (; i >= 0; i--) { - if (_this.get_Chars(i) == hi && _this.get_Chars(i+1) == lo) { - return i; - } - } - } - return -1; - } - - /** - * Returns the index within this string of the first occurrence of the - * specified substring. - * - * <p>The returned index is the smallest value <i>k</i> for which: - * <blockquote><pre> - * this.startsWith(str, <i>k</i>) - * </pre></blockquote> - * If no such value of <i>k</i> exists, then {@code -1} is returned. - * - * @param str the substring to search for. - * @return the index of the first occurrence of the specified substring, - * or {@code -1} if there is no such occurrence. - */ - static int indexOf(String _this, String str) { - return indexOf(_this, str, 0); - } - - /** - * Returns the index within this string of the first occurrence of the - * specified substring, starting at the specified index. - * - * <p>The returned index is the smallest value <i>k</i> for which: - * <blockquote><pre> - * <i>k</i> >= fromIndex && this.startsWith(str, <i>k</i>) - * </pre></blockquote> - * If no such value of <i>k</i> exists, then {@code -1} is returned. - * - * @param str the substring to search for. - * @param fromIndex the index from which to start the search. - * @return the index of the first occurrence of the specified substring, - * starting at the specified index, - * or {@code -1} if there is no such occurrence. - */ - static int indexOf(String _this, String str, int fromIndex) { - // start by dereferencing _this, to make sure we throw a NullPointerException if _this is null - int slen = _this.length(); - int olen = str.length(); - if (olen == 0) - { - return Math.max(0, Math.min(fromIndex, slen)); - } - if (olen > slen) - { - return -1; - } - char firstChar = str.charAt(0); - // Java allows fromIndex to both below zero or above the length of the string, .NET doesn't - int index = Math.max(0, Math.min(slen, fromIndex)); - int end = slen - olen; - while (index >= 0 && index <= end) - { - if (cli.System.String.CompareOrdinal(_this, index, str, 0, olen) == 0) - { - return index; - } - index = _this.indexOf(firstChar, index + 1); - } - return -1; - } - - /** - * Code shared by String and StringBuffer to do searches. The - * source is the character array being searched, and the target - * is the string being searched for. - * - * @param source the characters being searched. - * @param sourceOffset offset of the source string. - * @param sourceCount count of the source string. - * @param target the characters being searched for. - * @param targetOffset offset of the target string. - * @param targetCount count of the target string. - * @param fromIndex the index to begin searching from. - */ - static int indexOf(char[] source, int sourceOffset, int sourceCount, - char[] target, int targetOffset, int targetCount, - int fromIndex) { - if (fromIndex >= sourceCount) { - return (targetCount == 0 ? sourceCount : -1); - } - if (fromIndex < 0) { - fromIndex = 0; - } - if (targetCount == 0) { - return fromIndex; - } - - char first = target[targetOffset]; - int max = sourceOffset + (sourceCount - targetCount); - - for (int i = sourceOffset + fromIndex; i <= max; i++) { - /* Look for first character. */ - if (source[i] != first) { - while (++i <= max && source[i] != first); - } - - /* Found first character, now look at the rest of v2 */ - if (i <= max) { - int j = i + 1; - int end = j + targetCount - 1; - for (int k = targetOffset + 1; j < end && source[j] - == target[k]; j++, k++); - - if (j == end) { - /* Found whole string. */ - return i - sourceOffset; - } - } - } - return -1; - } - - /** - * Returns the index within this string of the last occurrence of the - * specified substring. The last occurrence of the empty string "" - * is considered to occur at the index value {@code this.length()}. - * - * <p>The returned index is the largest value <i>k</i> for which: - * <blockquote><pre> - * this.startsWith(str, <i>k</i>) - * </pre></blockquote> - * If no such value of <i>k</i> exists, then {@code -1} is returned. - * - * @param str the substring to search for. - * @return the index of the last occurrence of the specified substring, - * or {@code -1} if there is no such occurrence. - */ - static int lastIndexOf(String _this, String str) { - return lastIndexOf(_this, str, _this.length()); - } - - /** - * Returns the index within this string of the last occurrence of the - * specified substring, searching backward starting at the specified index. - * - * <p>The returned index is the largest value <i>k</i> for which: - * <blockquote><pre> - * <i>k</i> <= fromIndex && this.startsWith(str, <i>k</i>) - * </pre></blockquote> - * If no such value of <i>k</i> exists, then {@code -1} is returned. - * - * @param str the substring to search for. - * @param fromIndex the index to start the search from. - * @return the index of the last occurrence of the specified substring, - * searching backward from the specified index, - * or {@code -1} if there is no such occurrence. - */ - static int lastIndexOf(String _this, String str, int fromIndex) { - // start by dereferencing s, to make sure we throw a NullPointerException if s is null - int slen = _this.length(); - if (fromIndex < 0) - { - return -1; - } - int olen = str.length(); - if (olen == 0) - { - return Math.min(slen, fromIndex); - } - if (olen > slen) - { - return -1; - } - cli.System.String cliStr = (cli.System.String)(Object)_this; - char firstChar = str.charAt(0); - // Java allows fromIndex to both below zero or above the length of the string, .NET doesn't - int index = Math.max(0, Math.min(slen - olen, fromIndex)); - while (index > 0) - { - if (cli.System.String.CompareOrdinal(_this, index, str, 0, olen) == 0) - { - return index; - } - index = cliStr.LastIndexOf(firstChar, index - 1); - } - return cli.System.String.CompareOrdinal(_this, 0, str, 0, olen) == 0 ? 0 : -1; - } - - /** - * Code shared by String and StringBuffer to do searches. The - * source is the character array being searched, and the target - * is the string being searched for. - * - * @param source the characters being searched. - * @param sourceOffset offset of the source string. - * @param sourceCount count of the source string. - * @param target the characters being searched for. - * @param targetOffset offset of the target string. - * @param targetCount count of the target string. - * @param fromIndex the index to begin searching from. - */ - static int lastIndexOf(char[] source, int sourceOffset, int sourceCount, - char[] target, int targetOffset, int targetCount, - int fromIndex) { - /* - * Check arguments; return immediately where possible. For - * consistency, don't check for null str. - */ - int rightIndex = sourceCount - targetCount; - if (fromIndex < 0) { - return -1; - } - if (fromIndex > rightIndex) { - fromIndex = rightIndex; - } - /* Empty string always matches. */ - if (targetCount == 0) { - return fromIndex; - } - - int strLastIndex = targetOffset + targetCount - 1; - char strLastChar = target[strLastIndex]; - int min = sourceOffset + targetCount - 1; - int i = min + fromIndex; - - startSearchForLastChar: - while (true) { - while (i >= min && source[i] != strLastChar) { - i--; - } - if (i < min) { - return -1; - } - int j = i - 1; - int start = j - (targetCount - 1); - int k = strLastIndex - 1; - - while (j > start) { - if (source[j--] != target[k--]) { - i--; - continue startSearchForLastChar; - } - } - return start - sourceOffset + 1; - } - } - - /** - * Returns a new string that is a substring of this string. The - * substring begins at the specified <code>beginIndex</code> and - * extends to the character at index <code>endIndex - 1</code>. - * Thus the length of the substring is <code>endIndex-beginIndex</code>. - * <p> - * Examples: - * <blockquote><pre> - * "hamburger".substring(4, 8) returns "urge" - * "smiles".substring(1, 5) returns "mile" - * </pre></blockquote> - * - * @param beginIndex the beginning index, inclusive. - * @param endIndex the ending index, exclusive. - * @return the specified substring. - * @exception IndexOutOfBoundsException if the - * <code>beginIndex</code> is negative, or - * <code>endIndex</code> is larger than the length of - * this <code>String</code> object, or - * <code>beginIndex</code> is larger than - * <code>endIndex</code>. - */ - static String substring(cli.System.String _this, int beginIndex, int endIndex) { - if (beginIndex < 0) { - throw new StringIndexOutOfBoundsException(beginIndex); - } - if (endIndex > _this.get_Length()) { - throw new StringIndexOutOfBoundsException(endIndex); - } - int subLen = endIndex - beginIndex; - if (subLen < 0) { - throw new StringIndexOutOfBoundsException(subLen); - } - return ((beginIndex == 0) && (endIndex == _this.get_Length())) ? (String)(Object)_this - : _this.Substring(beginIndex, subLen); - } - - /** - * Concatenates the specified string to the end of this string. - * <p> - * If the length of the argument string is <code>0</code>, then this - * <code>String</code> object is returned. Otherwise, a new - * <code>String</code> object is created, representing a character - * sequence that is the concatenation of the character sequence - * represented by this <code>String</code> object and the character - * sequence represented by the argument string.<p> - * Examples: - * <blockquote><pre> - * "cares".concat("s") returns "caress" - * "to".concat("get").concat("her") returns "together" - * </pre></blockquote> - * - * @param str the <code>String</code> that is concatenated to the end - * of this <code>String</code>. - * @return a string that represents the concatenation of this object's - * characters followed by the string argument's characters. - */ - static String concat(String _this, String str) { - int otherLen = str.length(); - if (otherLen == 0) { - return _this; - } - return cli.System.String.Concat(_this, str); - } - - /** - * Returns a new string resulting from replacing all occurrences of - * <code>oldChar</code> in this string with <code>newChar</code>. - * <p> - * If the character <code>oldChar</code> does not occur in the - * character sequence represented by this <code>String</code> object, - * then a reference to this <code>String</code> object is returned. - * Otherwise, a new <code>String</code> object is created that - * represents a character sequence identical to the character sequence - * represented by this <code>String</code> object, except that every - * occurrence of <code>oldChar</code> is replaced by an occurrence - * of <code>newChar</code>. - * <p> - * Examples: - * <blockquote><pre> - * "mesquite in your cellar".replace('e', 'o') - * returns "mosquito in your collar" - * "the war of baronets".replace('r', 'y') - * returns "the way of bayonets" - * "sparring with a purple porpoise".replace('p', 't') - * returns "starring with a turtle tortoise" - * "JonL".replace('q', 'x') returns "JonL" (no change) - * </pre></blockquote> - * - * @param oldChar the old character. - * @param newChar the new character. - * @return a string derived from this string by replacing every - * occurrence of <code>oldChar</code> with <code>newChar</code>. - */ - static String replace(String _this, char oldChar, char newChar) { - if (oldChar != newChar) { - int len = _this.length(); - int i = -1; - - while (++i < len) { - if (_this.charAt(i) == oldChar) { - break; - } - } - if (i < len) { - char buf[] = new char[len]; - for (int j = 0 ; j < i ; j++) { - buf[j] = _this.charAt(j); - } - while (i < len) { - char c = _this.charAt(i); - buf[i] = (c == oldChar) ? newChar : c; - i++; - } - return new String(buf, true); - } - } - return _this; - } - - /** - * Returns true if and only if this string contains the specified - * sequence of char values. - * - * @param s the sequence to search for - * @return true if this string contains <code>s</code>, false otherwise - * @throws NullPointerException if <code>s</code> is <code>null</code> - * @since 1.5 - */ - static boolean contains(String _this, CharSequence s) { - return indexOf(_this, s.toString()) > -1; - } - - /** - * Replaces each substring of this string that matches the literal target - * sequence with the specified literal replacement sequence. The - * replacement proceeds from the beginning of the string to the end, for - * example, replacing "aa" with "b" in the string "aaa" will result in - * "ba" rather than "ab". - * - * @param target The sequence of char values to be replaced - * @param replacement The replacement sequence of char values - * @return The resulting string - * @throws NullPointerException if <code>target</code> or - * <code>replacement</code> is <code>null</code>. - * @since 1.5 - */ - static String replace(String _this, CharSequence target, CharSequence replacement) { - return Pattern.compile(target.toString(), Pattern.LITERAL).matcher( - _this).replaceAll(Matcher.quoteReplacement(replacement.toString())); - } - - /** - * Splits this string around matches of the given - * <a href="../util/regex/Pattern.html#sum">regular expression</a>. - * - * <p> The array returned by this method contains each substring of this - * string that is terminated by another substring that matches the given - * expression or is terminated by the end of the string. The substrings in - * the array are in the order in which they occur in this string. If the - * expression does not match any part of the input then the resulting array - * has just one element, namely this string. - * - * <p> The <tt>limit</tt> parameter controls the number of times the - * pattern is applied and therefore affects the length of the resulting - * array. If the limit <i>n</i> is greater than zero then the pattern - * will be applied at most <i>n</i> - 1 times, the array's - * length will be no greater than <i>n</i>, and the array's last entry - * will contain all input beyond the last matched delimiter. If <i>n</i> - * is non-positive then the pattern will be applied as many times as - * possible and the array can have any length. If <i>n</i> is zero then - * the pattern will be applied as many times as possible, the array can - * have any length, and trailing empty strings will be discarded. - * - * <p> The string <tt>"boo:and:foo"</tt>, for example, yields the - * following results with these parameters: - * - * <blockquote><table cellpadding=1 cellspacing=0 summary="Split example showing regex, limit, and result"> - * <tr> - * <th>Regex</th> - * <th>Limit</th> - * <th>Result</th> - * </tr> - * <tr><td align=center>:</td> - * <td align=center>2</td> - * <td><tt>{ "boo", "and:foo" }</tt></td></tr> - * <tr><td align=center>:</td> - * <td align=center>5</td> - * <td><tt>{ "boo", "and", "foo" }</tt></td></tr> - * <tr><td align=center>:</td> - * <td align=center>-2</td> - * <td><tt>{ "boo", "and", "foo" }</tt></td></tr> - * <tr><td align=center>o</td> - * <td align=center>5</td> - * <td><tt>{ "b", "", ":and:f", "", "" }</tt></td></tr> - * <tr><td align=center>o</td> - * <td align=center>-2</td> - * <td><tt>{ "b", "", ":and:f", "", "" }</tt></td></tr> - * <tr><td align=center>o</td> - * <td align=center>0</td> - * <td><tt>{ "b", "", ":and:f" }</tt></td></tr> - * </table></blockquote> - * - * <p> An invocation of this method of the form - * <i>str.</i><tt>split(</tt><i>regex</i><tt>,</tt> <i>n</i><tt>)</tt> - * yields the same result as the expression - * - * <blockquote> - * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile - * compile}<tt>(</tt><i>regex</i><tt>)</tt>.{@link - * java.util.regex.Pattern#split(java.lang.CharSequence,int) - * split}<tt>(</tt><i>str</i><tt>,</tt> <i>n</i><tt>)</tt> - * </blockquote> - * - * - * @param regex - * the delimiting regular expression - * - * @param limit - * the result threshold, as described above - * - * @return the array of strings computed by splitting this string - * around matches of the given regular expression - * - * @throws PatternSyntaxException - * if the regular expression's syntax is invalid - * - * @see java.util.regex.Pattern - * - * @since 1.4 - * @spec JSR-51 - */ - static String[] split(String _this, String regex, int limit) { - /* fastpath if the regex is a - (1)one-char String and this character is not one of the - RegEx's meta characters ".$|()[{^?*+\\", or - (2)two-char String and the first char is the backslash and - the second is not the ascii digit or ascii letter. - */ - char ch = 0; - if (((regex.length() == 1 && - ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) || - (regex.length() == 2 && - regex.charAt(0) == '\\' && - (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 && - ((ch-'a')|('z'-ch)) < 0 && - ((ch-'A')|('Z'-ch)) < 0)) && - (ch < Character.MIN_HIGH_SURROGATE || - ch > Character.MAX_LOW_SURROGATE)) - { - int off = 0; - int next = 0; - boolean limited = limit > 0; - ArrayList<String> list = new ArrayList<>(); - while ((next = _this.indexOf(ch, off)) != -1) { - if (!limited || list.size() < limit - 1) { - list.add(_this.substring(off, next)); - off = next + 1; - } else { // last one - //assert (list.size() == limit - 1); - list.add(_this.substring(off, _this.length())); - off = _this.length(); - break; - } - } - // If no match was found, return this - if (off == 0) - return new String[]{_this}; - - // Add remaining segment - if (!limited || list.size() < limit) - list.add(_this.substring(off, _this.length())); - - // Construct result - int resultSize = list.size(); - if (limit == 0) - while (resultSize > 0 && list.get(resultSize - 1).length() == 0) - resultSize--; - String[] result = new String[resultSize]; - return list.subList(0, resultSize).toArray(result); - } - return Pattern.compile(regex).split(_this, limit); - } - - /** - * Converts all of the characters in this <code>String</code> to lower - * case using the rules of the given <code>Locale</code>. Case mapping is based - * on the Unicode Standard version specified by the {@link java.lang.Character Character} - * class. Since case mappings are not always 1:1 char mappings, the resulting - * <code>String</code> may be a different length than the original <code>String</code>. - * <p> - * Examples of lowercase mappings are in the following table: - * <table border="1" summary="Lowercase mapping examples showing language code of locale, upper case, lower case, and description"> - * <tr> - * <th>Language Code of Locale</th> - * <th>Upper Case</th> - * <th>Lower Case</th> - * <th>Description</th> - * </tr> - * <tr> - * <td>tr (Turkish)</td> - * <td>\u0130</td> - * <td>\u0069</td> - * <td>capital letter I with dot above -> small letter i</td> - * </tr> - * <tr> - * <td>tr (Turkish)</td> - * <td>\u0049</td> - * <td>\u0131</td> - * <td>capital letter I -> small letter dotless i </td> - * </tr> - * <tr> - * <td>(all)</td> - * <td>French Fries</td> - * <td>french fries</td> - * <td>lowercased all chars in String</td> - * </tr> - * <tr> - * <td>(all)</td> - * <td><img src="doc-files/capiota.gif" alt="capiota"><img src="doc-files/capchi.gif" alt="capchi"> - * <img src="doc-files/captheta.gif" alt="captheta"><img src="doc-files/capupsil.gif" alt="capupsil"> - * <img src="doc-files/capsigma.gif" alt="capsigma"></td> - * <td><img src="doc-files/iota.gif" alt="iota"><img src="doc-files/chi.gif" alt="chi"> - * <img src="doc-files/theta.gif" alt="theta"><img src="doc-files/upsilon.gif" alt="upsilon"> - * <img src="doc-files/sigma1.gif" alt="sigma"></td> - * <td>lowercased all chars in String</td> - * </tr> - * </table> - * - * @param locale use the case transformation rules for this locale - * @return the <code>String</code>, converted to lowercase. - * @see java.lang.String#toLowerCase() - * @see java.lang.String#toUpperCase() - * @see java.lang.String#toUpperCase(Locale) - * @since 1.1 - */ - static String toLowerCase(String _this, Locale locale) { - if (locale == null) { - throw new NullPointerException(); - } - - int firstUpper; - final int len = _this.length(); - - /* Now check if there are any characters that need to be changed. */ - scan: { - for (firstUpper = 0 ; firstUpper < len; ) { - char c = _this.charAt(firstUpper); - if ((c >= Character.MIN_HIGH_SURROGATE) - && (c <= Character.MAX_HIGH_SURROGATE)) { - int supplChar = _this.codePointAt(firstUpper); - if (supplChar != Character.toLowerCase(supplChar)) { - break scan; - } - firstUpper += Character.charCount(supplChar); - } else { - if (c != Character.toLowerCase(c)) { - break scan; - } - firstUpper++; - } - } - return _this; - } - - char[] result = new char[len]; - int resultOffset = 0; /* result may grow, so i+resultOffset - * is the write location in result */ - - /* Just copy the first few lowerCase characters. */ - _this.getChars(0, firstUpper, result, 0); - - String lang = locale.getLanguage(); - boolean localeDependent = - (lang == "tr" || lang == "az" || lang == "lt"); - char[] lowerCharArray; - int lowerChar; - int srcChar; - int srcCount; - for (int i = firstUpper; i < len; i += srcCount) { - srcChar = (int)_this.charAt(i); - if ((char)srcChar >= Character.MIN_HIGH_SURROGATE - && (char)srcChar <= Character.MAX_HIGH_SURROGATE) { - srcChar = _this.codePointAt(i); - srcCount = Character.charCount(srcChar); - } else { - srcCount = 1; - } - if (localeDependent || srcChar == '\u03A3') { // GREEK CAPITAL LETTER SIGMA - lowerChar = ConditionalSpecialCasing.toLowerCaseEx(_this, i, locale); - } else if (srcChar == '\u0130') { // LATIN CAPITAL LETTER I DOT - lowerChar = Character.ERROR; - } else { - lowerChar = Character.toLowerCase(srcChar); - } - if ((lowerChar == Character.ERROR) - || (lowerChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) { - if (lowerChar == Character.ERROR) { - if (!localeDependent && srcChar == '\u0130') { - lowerCharArray = - ConditionalSpecialCasing.toLowerCaseCharArray(_this, i, Locale.ENGLISH); - } else { - lowerCharArray = - ConditionalSpecialCasing.toLowerCaseCharArray(_this, i, locale); - } - } else if (srcCount == 2) { - resultOffset += Character.toChars(lowerChar, result, i + resultOffset) - srcCount; - continue; - } else { - lowerCharArray = Character.toChars(lowerChar); - } - - /* Grow result if needed */ - int mapLen = lowerCharArray.length; - if (mapLen > srcCount) { - char[] result2 = new char[result.length + mapLen - srcCount]; - System.arraycopy(result, 0, result2, 0, i + resultOffset); - result = result2; - } - for (int x = 0; x < mapLen; ++x) { - result[i + resultOffset + x] = lowerCharArray[x]; - } - resultOffset += (mapLen - srcCount); - } else { - result[i + resultOffset] = (char)lowerChar; - } - } - return new String(result, 0, len + resultOffset); - } - - /** - * Converts all of the characters in this <code>String</code> to lower - * case using the rules of the default locale. This is equivalent to calling - * <code>toLowerCase(Locale.getDefault())</code>. - * <p> - * <b>Note:</b> This method is locale sensitive, and may produce unexpected - * results if used for strings that are intended to be interpreted locale - * independently. - * Examples are programming language identifiers, protocol keys, and HTML - * tags. - * For instance, <code>"TITLE".toLowerCase()</code> in a Turkish locale - * returns <code>"t\u005Cu0131tle"</code>, where '\u005Cu0131' is the - * LATIN SMALL LETTER DOTLESS I character. - * To obtain correct results for locale insensitive strings, use - * <code>toLowerCase(Locale.ENGLISH)</code>. - * <p> - * @return the <code>String</code>, converted to lowercase. - * @see java.lang.String#toLowerCase(Locale) - */ - static String toLowerCase(String _this) { - return toLowerCase(_this, Locale.getDefault()); - } - - /** - * Converts all of the characters in this <code>String</code> to upper - * case using the rules of the given <code>Locale</code>. Case mapping is based - * on the Unicode Standard version specified by the {@link java.lang.Character Character} - * class. Since case mappings are not always 1:1 char mappings, the resulting - * <code>String</code> may be a different length than the original <code>String</code>. - * <p> - * Examples of locale-sensitive and 1:M case mappings are in the following table. - * <p> - * <table border="1" summary="Examples of locale-sensitive and 1:M case mappings. Shows Language code of locale, lower case, upper case, and description."> - * <tr> - * <th>Language Code of Locale</th> - * <th>Lower Case</th> - * <th>Upper Case</th> - * <th>Description</th> - * </tr> - * <tr> - * <td>tr (Turkish)</td> - * <td>\u0069</td> - * <td>\u0130</td> - * <td>small letter i -> capital letter I with dot above</td> - * </tr> - * <tr> - * <td>tr (Turkish)</td> - * <td>\u0131</td> - * <td>\u0049</td> - * <td>small letter dotless i -> capital letter I</td> - * </tr> - * <tr> - * <td>(all)</td> - * <td>\u00df</td> - * <td>\u0053 \u0053</td> - * <td>small letter sharp s -> two letters: SS</td> - * </tr> - * <tr> - * <td>(all)</td> - * <td>Fahrvergnügen</td> - * <td>FAHRVERGNÜGEN</td> - * <td></td> - * </tr> - * </table> - * @param locale use the case transformation rules for this locale - * @return the <code>String</code>, converted to uppercase. - * @see java.lang.String#toUpperCase() - * @see java.lang.String#toLowerCase() - * @see java.lang.String#toLowerCase(Locale) - * @since 1.1 - */ - static String toUpperCase(String _this, Locale locale) { - if (locale == null) { - throw new NullPointerException(); - } - - int firstLower; - final int len = _this.length(); - - /* Now check if there are any characters that need to be changed. */ - scan: { - for (firstLower = 0 ; firstLower < len; ) { - int c = (int)_this.charAt(firstLower); - int srcCount; - if ((c >= Character.MIN_HIGH_SURROGATE) - && (c <= Character.MAX_HIGH_SURROGATE)) { - c = _this.codePointAt(firstLower); - srcCount = Character.charCount(c); - } else { - srcCount = 1; - } - int upperCaseChar = Character.toUpperCaseEx(c); - if ((upperCaseChar == Character.ERROR) - || (c != upperCaseChar)) { - break scan; - } - firstLower += srcCount; - } - return _this; - } - - char[] result = new char[len]; /* may grow */ - int resultOffset = 0; /* result may grow, so i+resultOffset - * is the write location in result */ - - /* Just copy the first few upperCase characters. */ - _this.getChars(0, firstLower, result, 0); - - String lang = locale.getLanguage(); - boolean localeDependent = - (lang == "tr" || lang == "az" || lang == "lt"); - char[] upperCharArray; - int upperChar; - int srcChar; - int srcCount; - for (int i = firstLower; i < len; i += srcCount) { - srcChar = (int)_this.charAt(i); - if ((char)srcChar >= Character.MIN_HIGH_SURROGATE && - (char)srcChar <= Character.MAX_HIGH_SURROGATE) { - srcChar = _this.codePointAt(i); - srcCount = Character.charCount(srcChar); - } else { - srcCount = 1; - } - if (localeDependent) { - upperChar = ConditionalSpecialCasing.toUpperCaseEx(_this, i, locale); - } else { - upperChar = Character.toUpperCaseEx(srcChar); - } - if ((upperChar == Character.ERROR) - || (upperChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) { - if (upperChar == Character.ERROR) { - if (localeDependent) { - upperCharArray = - ConditionalSpecialCasing.toUpperCaseCharArray(_this, i, locale); - } else { - upperCharArray = Character.toUpperCaseCharArray(srcChar); - } - } else if (srcCount == 2) { - resultOffset += Character.toChars(upperChar, result, i + resultOffset) - srcCount; - continue; - } else { - upperCharArray = Character.toChars(upperChar); - } - - /* Grow result if needed */ - int mapLen = upperCharArray.length; - if (mapLen > srcCount) { - char[] result2 = new char[result.length + mapLen - srcCount]; - System.arraycopy(result, 0, result2, 0, i + resultOffset); - result = result2; - } - for (int x = 0; x < mapLen; ++x) { - result[i + resultOffset + x] = upperCharArray[x]; - } - resultOffset += (mapLen - srcCount); - } else { - result[i + resultOffset] = (char)upperChar; - } - } - return new String(result, 0, len + resultOffset); - } - - /** - * Converts all of the characters in this <code>String</code> to upper - * case using the rules of the default locale. This method is equivalent to - * <code>toUpperCase(Locale.getDefault())</code>. - * <p> - * <b>Note:</b> This method is locale sensitive, and may produce unexpected - * results if used for strings that are intended to be interpreted locale - * independently. - * Examples are programming language identifiers, protocol keys, and HTML - * tags. - * For instance, <code>"title".toUpperCase()</code> in a Turkish locale - * returns <code>"T\u005Cu0130TLE"</code>, where '\u005Cu0130' is the - * LATIN CAPITAL LETTER I WITH DOT ABOVE character. - * To obtain correct results for locale insensitive strings, use - * <code>toUpperCase(Locale.ENGLISH)</code>. - * <p> - * @return the <code>String</code>, converted to uppercase. - * @see java.lang.String#toUpperCase(Locale) - */ - static String toUpperCase(String _this) { - return toUpperCase(_this, Locale.getDefault()); - } - - /** - * Returns a copy of the string, with leading and trailing whitespace - * omitted. - * <p> - * If this <code>String</code> object represents an empty character - * sequence, or the first and last characters of character sequence - * represented by this <code>String</code> object both have codes - * greater than <code>'\u0020'</code> (the space character), then a - * reference to this <code>String</code> object is returned. - * <p> - * Otherwise, if there is no character with a code greater than - * <code>'\u0020'</code> in the string, then a new - * <code>String</code> object representing an empty string is created - * and returned. - * <p> - * Otherwise, let <i>k</i> be the index of the first character in the - * string whose code is greater than <code>'\u0020'</code>, and let - * <i>m</i> be the index of the last character in the string whose code - * is greater than <code>'\u0020'</code>. A new <code>String</code> - * object is created, representing the substring of this string that - * begins with the character at index <i>k</i> and ends with the - * character at index <i>m</i>-that is, the result of - * <code>this.substring(<i>k</i>, <i>m</i>+1)</code>. - * <p> - * This method may be used to trim whitespace (as defined above) from - * the beginning and end of a string. - * - * @return A copy of this string with leading and trailing white - * space removed, or this string if it has no leading or - * trailing white space. - */ - static String trim(String _this) { - int len = _this.length(); - int st = 0; - - while ((st < len) && (_this.charAt(st) <= ' ')) { - st++; - } - while ((st < len) && (_this.charAt(len - 1) <= ' ')) { - len--; - } - return ((st > 0) || (len < _this.length())) ? _this.substring(st, len) : _this; - } - - /** - * Returns a formatted string using the specified format string and - * arguments. - * - * <p> The locale always used is the one returned by {@link - * java.util.Locale#getDefault() Locale.getDefault()}. - * - * @param format - * A <a href="../util/Formatter.html#syntax">format string</a> - * - * @param args - * Arguments referenced by the format specifiers in the format - * string. If there are more arguments than format specifiers, the - * extra arguments are ignored. The number of arguments is - * variable and may be zero. The maximum number of arguments is - * limited by the maximum dimension of a Java array as defined by - * <cite>The Java™ Virtual Machine Specification</cite>. - * The behaviour on a - * <tt>null</tt> argument depends on the <a - * href="../util/Formatter.html#syntax">conversion</a>. - * - * @throws IllegalFormatException - * If a format string contains an illegal syntax, a format - * specifier that is incompatible with the given arguments, - * insufficient arguments given the format string, or other - * illegal conditions. For specification of all possible - * formatting errors, see the <a - * href="../util/Formatter.html#detail">Details</a> section of the - * formatter class specification. - * - * @throws NullPointerException - * If the <tt>format</tt> is <tt>null</tt> - * - * @return A formatted string - * - * @see java.util.Formatter - * @since 1.5 - */ - public static String format(String format, Object... args) { - return new Formatter().format(format, args).toString(); - } - - /** - * Returns a formatted string using the specified locale, format string, - * and arguments. - * - * @param l - * The {@linkplain java.util.Locale locale} to apply during - * formatting. If <tt>l</tt> is <tt>null</tt> then no localization - * is applied. - * - * @param format - * A <a href="../util/Formatter.html#syntax">format string</a> - * - * @param args - * Arguments referenced by the format specifiers in the format - * string. If there are more arguments than format specifiers, the - * extra arguments are ignored. The number of arguments is - * variable and may be zero. The maximum number of arguments is - * limited by the maximum dimension of a Java array as defined by - * <cite>The Java™ Virtual Machine Specification</cite>. - * The behaviour on a - * <tt>null</tt> argument depends on the <a - * href="../util/Formatter.html#syntax">conversion</a>. - * - * @throws IllegalFormatException - * If a format string contains an illegal syntax, a format - * specifier that is incompatible with the given arguments, - * insufficient arguments given the format string, or other - * illegal conditions. For specification of all possible - * formatting errors, see the <a - * href="../util/Formatter.html#detail">Details</a> section of the - * formatter class specification - * - * @throws NullPointerException - * If the <tt>format</tt> is <tt>null</tt> - * - * @return A formatted string - * - * @see java.util.Formatter - * @since 1.5 - */ - public static String format(Locale l, String format, Object... args) { - return new Formatter(l).format(format, args).toString(); - } - - /** - * Returns the string representation of the <code>Object</code> argument. - * - * @param obj an <code>Object</code>. - * @return if the argument is <code>null</code>, then a string equal to - * <code>"null"</code>; otherwise, the value of - * <code>obj.toString()</code> is returned. - * @see java.lang.Object#toString() - */ - public static String valueOf(Object obj) { - return (obj == null) ? "null" : obj.toString(); - } - - /** - * Returns the string representation of the <code>char</code> array - * argument. The contents of the character array are copied; subsequent - * modification of the character array does not affect the newly - * created string. - * - * @param data a <code>char</code> array. - * @return a newly allocated string representing the same sequence of - * characters contained in the character array argument. - */ - public static String valueOf(char data[]) { - return new String(data); - } - - /** - * Returns the string representation of a specific subarray of the - * <code>char</code> array argument. - * <p> - * The <code>offset</code> argument is the index of the first - * character of the subarray. The <code>count</code> argument - * specifies the length of the subarray. The contents of the subarray - * are copied; subsequent modification of the character array does not - * affect the newly created string. - * - * @param data the character array. - * @param offset the initial offset into the value of the - * <code>String</code>. - * @param count the length of the value of the <code>String</code>. - * @return a string representing the sequence of characters contained - * in the subarray of the character array argument. - * @exception IndexOutOfBoundsException if <code>offset</code> is - * negative, or <code>count</code> is negative, or - * <code>offset+count</code> is larger than - * <code>data.length</code>. - */ - public static String valueOf(char data[], int offset, int count) { - return new String(data, offset, count); - } - - /** - * Returns a String that represents the character sequence in the - * array specified. - * - * @param data the character array. - * @param offset initial offset of the subarray. - * @param count length of the subarray. - * @return a <code>String</code> that contains the characters of the - * specified subarray of the character array. - */ - public static String copyValueOf(char data[], int offset, int count) { - // All public String constructors now copy the data. - return new String(data, offset, count); - } - - /** - * Returns a String that represents the character sequence in the - * array specified. - * - * @param data the character array. - * @return a <code>String</code> that contains the characters of the - * character array. - */ - public static String copyValueOf(char data[]) { - return new String(data); - } - - /** - * Returns the string representation of the <code>boolean</code> argument. - * - * @param b a <code>boolean</code>. - * @return if the argument is <code>true</code>, a string equal to - * <code>"true"</code> is returned; otherwise, a string equal to - * <code>"false"</code> is returned. - */ - public static String valueOf(boolean b) { - return b ? "true" : "false"; - } - - /** - * Returns the string representation of the <code>int</code> argument. - * <p> - * The representation is exactly the one returned by the - * <code>Integer.toString</code> method of one argument. - * - * @param i an <code>int</code>. - * @return a string representation of the <code>int</code> argument. - * @see java.lang.Integer#toString(int, int) - */ - public static String valueOf(int i) { - return Integer.toString(i); - } - - /** - * Returns the string representation of the <code>long</code> argument. - * <p> - * The representation is exactly the one returned by the - * <code>Long.toString</code> method of one argument. - * - * @param l a <code>long</code>. - * @return a string representation of the <code>long</code> argument. - * @see java.lang.Long#toString(long) - */ - public static String valueOf(long l) { - return Long.toString(l); - } - - /** - * Returns the string representation of the <code>float</code> argument. - * <p> - * The representation is exactly the one returned by the - * <code>Float.toString</code> method of one argument. - * - * @param f a <code>float</code>. - * @return a string representation of the <code>float</code> argument. - * @see java.lang.Float#toString(float) - */ - public static String valueOf(float f) { - return Float.toString(f); - } - - /** - * Returns the string representation of the <code>double</code> argument. - * <p> - * The representation is exactly the one returned by the - * <code>Double.toString</code> method of one argument. - * - * @param d a <code>double</code>. - * @return a string representation of the <code>double</code> argument. - * @see java.lang.Double#toString(double) - */ - public static String valueOf(double d) { - return Double.toString(d); - } - - /** - * Seed value used for each alternative hash calculated. - */ - private static final int HASHING_SEED; - - static { - long nanos = System.nanoTime(); - long now = System.currentTimeMillis(); - int SEED_MATERIAL[] = { - System.identityHashCode(String.class), - System.identityHashCode(System.class), - (int) (nanos >>> 32), - (int) nanos, - (int) (now >>> 32), - (int) now, - (int) (System.nanoTime() >>> 2) - }; - - // Use murmur3 to scramble the seeding material. - // Inline implementation to avoid loading classes - int h1 = 0; - - // body - for (int k1 : SEED_MATERIAL) { - k1 *= 0xcc9e2d51; - k1 = (k1 << 15) | (k1 >>> 17); - k1 *= 0x1b873593; - - h1 ^= k1; - h1 = (h1 << 13) | (h1 >>> 19); - h1 = h1 * 5 + 0xe6546b64; - } - - // tail (always empty, as body is always 32-bit chunks) - - // finalization - - h1 ^= SEED_MATERIAL.length * 4; - - // finalization mix force all bits of a hash block to avalanche - h1 ^= h1 >>> 16; - h1 *= 0x85ebca6b; - h1 ^= h1 >>> 13; - h1 *= 0xc2b2ae35; - h1 ^= h1 >>> 16; - - HASHING_SEED = h1; - } - - /** - * Calculates a 32-bit hash value for this string. - * - * @return a 32-bit hash value for this string. - */ - static int hash32(String _this) { - // [IKVM] We don't bother with murmur32 and just use the .NET hash code - // and hope that it is good enough. We xor with HASHING_SEED to avoid - // returning predictable values (this does not help against DoS attacks, - // but it will surface constant hash code dependencies). - // If truly randomized string hashes are required (to protect against - // DoS) the .NET 4.5 <UseRandomizedStringHashAlgorithm enabled="1" /> - // app.config setting can be used. - return HASHING_SEED ^ ((cli.System.String)(Object)_this).GetHashCode(); - } - -} diff --git a/openjdk/java/lang/System.java b/openjdk/java/lang/System.java deleted file mode 100644 index e74187b9..00000000 --- a/openjdk/java/lang/System.java +++ /dev/null @@ -1,1168 +0,0 @@ -/* - * Copyright (c) 1994, 2011, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package java.lang; - -import java.io.*; -import java.util.Properties; -import java.util.PropertyPermission; -import java.util.StringTokenizer; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.AllPermission; -import java.nio.channels.Channel; -import java.nio.channels.spi.SelectorProvider; -import sun.reflect.CallerSensitive; -import sun.reflect.Reflection; -import sun.security.util.SecurityConstants; - -final class StdIO -{ - private StdIO() { } - static InputStream in = new BufferedInputStream(new FileInputStream(FileDescriptor.in)); - static PrintStream out = new PrintStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.out), 128), true); - static PrintStream err = new PrintStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.err), 128), true); -} - -final class Props -{ - private Props() { } - - static Properties props; - static String lineSeparator; - - static - { - props = new Properties(); - VMSystemProperties.initProperties(props); - lineSeparator = props.getProperty("line.separator"); - - // after we've initialized the system properties, we need to fixate certain - // results that depend on system properties, because we don't want Java code to - // be able to change the behavior by setting these system properties. - ClassLoader.initializeLibraryPaths(props); - sun.misc.VM.saveAndRemoveProperties(props); - - // now that we've initialized the system properties (which are our only - // notion of "booting" the VM) we set the booted flag. - sun.misc.VM.booted(); - } -} - -/** - * The <code>System</code> class contains several useful class fields - * and methods. It cannot be instantiated. - * - * <p>Among the facilities provided by the <code>System</code> class - * are standard input, standard output, and error output streams; - * access to externally defined properties and environment - * variables; a means of loading files and libraries; and a utility - * method for quickly copying a portion of an array. - * - * @author unascribed - * @since JDK1.0 - */ -public final class System { - - /** Don't let anyone instantiate this class */ - private System() { - } - - /** - * The "standard" input stream. This stream is already - * open and ready to supply input data. Typically this stream - * corresponds to keyboard input or another input source specified by - * the host environment or user. - */ - @ikvm.lang.Property(get="get_in") - public final static InputStream in; - - static { in = null; } - - private static InputStream get_in() - { - return StdIO.in; - } - - /** - * The "standard" output stream. This stream is already - * open and ready to accept output data. Typically this stream - * corresponds to display output or another output destination - * specified by the host environment or user. - * <p> - * For simple stand-alone Java applications, a typical way to write - * a line of output data is: - * <blockquote><pre> - * System.out.println(data) - * </pre></blockquote> - * <p> - * See the <code>println</code> methods in class <code>PrintStream</code>. - * - * @see java.io.PrintStream#println() - * @see java.io.PrintStream#println(boolean) - * @see java.io.PrintStream#println(char) - * @see java.io.PrintStream#println(char[]) - * @see java.io.PrintStream#println(double) - * @see java.io.PrintStream#println(float) - * @see java.io.PrintStream#println(int) - * @see java.io.PrintStream#println(long) - * @see java.io.PrintStream#println(java.lang.Object) - * @see java.io.PrintStream#println(java.lang.String) - */ - @ikvm.lang.Property(get="get_out") - public final static PrintStream out; - - static { out = null; } - - private static PrintStream get_out() - { - return StdIO.out; - } - - /** - * The "standard" error output stream. This stream is already - * open and ready to accept output data. - * <p> - * Typically this stream corresponds to display output or another - * output destination specified by the host environment or user. By - * convention, this output stream is used to display error messages - * or other information that should come to the immediate attention - * of a user even if the principal output stream, the value of the - * variable <code>out</code>, has been redirected to a file or other - * destination that is typically not continuously monitored. - */ - @ikvm.lang.Property(get="get_err") - public final static PrintStream err; - - static { err = null ; } - - private static PrintStream get_err() - { - return StdIO.err; - } - - /* The security manager for the system. - */ - private static volatile SecurityManager security; - - /** - * Reassigns the "standard" input stream. - * - * <p>First, if there is a security manager, its <code>checkPermission</code> - * method is called with a <code>RuntimePermission("setIO")</code> permission - * to see if it's ok to reassign the "standard" input stream. - * <p> - * - * @param in the new standard input stream. - * - * @throws SecurityException - * if a security manager exists and its - * <code>checkPermission</code> method doesn't allow - * reassigning of the standard input stream. - * - * @see SecurityManager#checkPermission - * @see java.lang.RuntimePermission - * - * @since JDK1.1 - */ - public static void setIn(InputStream in) { - checkIO(); - StdIO.in = in; - } - - /** - * Reassigns the "standard" output stream. - * - * <p>First, if there is a security manager, its <code>checkPermission</code> - * method is called with a <code>RuntimePermission("setIO")</code> permission - * to see if it's ok to reassign the "standard" output stream. - * - * @param out the new standard output stream - * - * @throws SecurityException - * if a security manager exists and its - * <code>checkPermission</code> method doesn't allow - * reassigning of the standard output stream. - * - * @see SecurityManager#checkPermission - * @see java.lang.RuntimePermission - * - * @since JDK1.1 - */ - public static void setOut(PrintStream out) { - checkIO(); - StdIO.out = out; - } - - /** - * Reassigns the "standard" error output stream. - * - * <p>First, if there is a security manager, its <code>checkPermission</code> - * method is called with a <code>RuntimePermission("setIO")</code> permission - * to see if it's ok to reassign the "standard" error output stream. - * - * @param err the new standard error output stream. - * - * @throws SecurityException - * if a security manager exists and its - * <code>checkPermission</code> method doesn't allow - * reassigning of the standard error output stream. - * - * @see SecurityManager#checkPermission - * @see java.lang.RuntimePermission - * - * @since JDK1.1 - */ - public static void setErr(PrintStream err) { - checkIO(); - StdIO.err = err; - } - - private static volatile Console cons; - /** - * Returns the unique {@link java.io.Console Console} object associated - * with the current Java virtual machine, if any. - * - * @return The system console, if any, otherwise <tt>null</tt>. - * - * @since 1.6 - */ - public static Console console() { - if (cons == null) { - synchronized (System.class) { - cons = sun.misc.SharedSecrets.getJavaIOAccess().console(); - } - } - return cons; - } - - /** - * Returns the channel inherited from the entity that created this - * Java virtual machine. - * - * <p> This method returns the channel obtained by invoking the - * {@link java.nio.channels.spi.SelectorProvider#inheritedChannel - * inheritedChannel} method of the system-wide default - * {@link java.nio.channels.spi.SelectorProvider} object. </p> - * - * <p> In addition to the network-oriented channels described in - * {@link java.nio.channels.spi.SelectorProvider#inheritedChannel - * inheritedChannel}, this method may return other kinds of - * channels in the future. - * - * @return The inherited channel, if any, otherwise <tt>null</tt>. - * - * @throws IOException - * If an I/O error occurs - * - * @throws SecurityException - * If a security manager is present and it does not - * permit access to the channel. - * - * @since 1.5 - */ - public static Channel inheritedChannel() throws IOException { - return SelectorProvider.provider().inheritedChannel(); - } - - private static void checkIO() { - SecurityManager sm = getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("setIO")); - } - } - - /** - * Sets the System security. - * - * <p> If there is a security manager already installed, this method first - * calls the security manager's <code>checkPermission</code> method - * with a <code>RuntimePermission("setSecurityManager")</code> - * permission to ensure it's ok to replace the existing - * security manager. - * This may result in throwing a <code>SecurityException</code>. - * - * <p> Otherwise, the argument is established as the current - * security manager. If the argument is <code>null</code> and no - * security manager has been established, then no action is taken and - * the method simply returns. - * - * @param s the security manager. - * @exception SecurityException if the security manager has already - * been set and its <code>checkPermission</code> method - * doesn't allow it to be replaced. - * @see #getSecurityManager - * @see SecurityManager#checkPermission - * @see java.lang.RuntimePermission - */ - public static - void setSecurityManager(final SecurityManager s) { - try { - s.checkPackageAccess("java.lang"); - } catch (Exception e) { - // no-op - } - setSecurityManager0(s); - } - - private static synchronized - void setSecurityManager0(final SecurityManager s) { - // [IKVM] force sun.misc.Launcher to initialize, because it assumes that it runs without a SecurityManager - sun.misc.Launcher.getLauncher(); - - SecurityManager sm = getSecurityManager(); - if (sm != null) { - // ask the currently installed security manager if we - // can replace it. - sm.checkPermission(new RuntimePermission - ("setSecurityManager")); - } - - if ((s != null) && (s.getClass().getClassLoader() != null)) { - // New security manager class is not on bootstrap classpath. - // Cause policy to get initialized before we install the new - // security manager, in order to prevent infinite loops when - // trying to initialize the policy (which usually involves - // accessing some security and/or system properties, which in turn - // calls the installed security manager's checkPermission method - // which will loop infinitely if there is a non-system class - // (in this case: the new security manager class) on the stack). - AccessController.doPrivileged(new PrivilegedAction<Object>() { - public Object run() { - s.getClass().getProtectionDomain().implies - (SecurityConstants.ALL_PERMISSION); - return null; - } - }); - } - - security = s; - } - - /** - * Gets the system security interface. - * - * @return if a security manager has already been established for the - * current application, then that security manager is returned; - * otherwise, <code>null</code> is returned. - * @see #setSecurityManager - */ - public static SecurityManager getSecurityManager() { - return security; - } - - /** - * Returns the current time in milliseconds. Note that - * while the unit of time of the return value is a millisecond, - * the granularity of the value depends on the underlying - * operating system and may be larger. For example, many - * operating systems measure time in units of tens of - * milliseconds. - * - * <p> See the description of the class <code>Date</code> for - * a discussion of slight discrepancies that may arise between - * "computer time" and coordinated universal time (UTC). - * - * @return the difference, measured in milliseconds, between - * the current time and midnight, January 1, 1970 UTC. - * @see java.util.Date - */ - public static long currentTimeMillis() { - long january_1st_1970 = 62135596800000L; - return cli.System.DateTime.get_UtcNow().get_Ticks() / 10000L - january_1st_1970; - } - - /** - * Returns the current value of the running Java Virtual Machine's - * high-resolution time source, in nanoseconds. - * - * <p>This method can only be used to measure elapsed time and is - * not related to any other notion of system or wall-clock time. - * The value returned represents nanoseconds since some fixed but - * arbitrary <i>origin</i> time (perhaps in the future, so values - * may be negative). The same origin is used by all invocations of - * this method in an instance of a Java virtual machine; other - * virtual machine instances are likely to use a different origin. - * - * <p>This method provides nanosecond precision, but not necessarily - * nanosecond resolution (that is, how frequently the value changes) - * - no guarantees are made except that the resolution is at least as - * good as that of {@link #currentTimeMillis()}. - * - * <p>Differences in successive calls that span greater than - * approximately 292 years (2<sup>63</sup> nanoseconds) will not - * correctly compute elapsed time due to numerical overflow. - * - * <p>The values returned by this method become meaningful only when - * the difference between two such values, obtained within the same - * instance of a Java virtual machine, is computed. - * - * <p> For example, to measure how long some code takes to execute: - * <pre> {@code - * long startTime = System.nanoTime(); - * // ... the code being measured ... - * long estimatedTime = System.nanoTime() - startTime;}</pre> - * - * <p>To compare two nanoTime values - * <pre> {@code - * long t0 = System.nanoTime(); - * ... - * long t1 = System.nanoTime();}</pre> - * - * one should use {@code t1 - t0 < 0}, not {@code t1 < t0}, - * because of the possibility of numerical overflow. - * - * @return the current value of the running Java Virtual Machine's - * high-resolution time source, in nanoseconds - * @since 1.5 - */ - public static long nanoTime() { - long NANOS_PER_SEC = 1000000000; - double current = cli.System.Diagnostics.Stopwatch.GetTimestamp(); - double freq = cli.System.Diagnostics.Stopwatch.Frequency; - return (long)((current / freq) * NANOS_PER_SEC); - } - - /** - * Copies an array from the specified source array, beginning at the - * specified position, to the specified position of the destination array. - * A subsequence of array components are copied from the source - * array referenced by <code>src</code> to the destination array - * referenced by <code>dest</code>. The number of components copied is - * equal to the <code>length</code> argument. The components at - * positions <code>srcPos</code> through - * <code>srcPos+length-1</code> in the source array are copied into - * positions <code>destPos</code> through - * <code>destPos+length-1</code>, respectively, of the destination - * array. - * <p> - * If the <code>src</code> and <code>dest</code> arguments refer to the - * same array object, then the copying is performed as if the - * components at positions <code>srcPos</code> through - * <code>srcPos+length-1</code> were first copied to a temporary - * array with <code>length</code> components and then the contents of - * the temporary array were copied into positions - * <code>destPos</code> through <code>destPos+length-1</code> of the - * destination array. - * <p> - * If <code>dest</code> is <code>null</code>, then a - * <code>NullPointerException</code> is thrown. - * <p> - * If <code>src</code> is <code>null</code>, then a - * <code>NullPointerException</code> is thrown and the destination - * array is not modified. - * <p> - * Otherwise, if any of the following is true, an - * <code>ArrayStoreException</code> is thrown and the destination is - * not modified: - * <ul> - * <li>The <code>src</code> argument refers to an object that is not an - * array. - * <li>The <code>dest</code> argument refers to an object that is not an - * array. - * <li>The <code>src</code> argument and <code>dest</code> argument refer - * to arrays whose component types are different primitive types. - * <li>The <code>src</code> argument refers to an array with a primitive - * component type and the <code>dest</code> argument refers to an array - * with a reference component type. - * <li>The <code>src</code> argument refers to an array with a reference - * component type and the <code>dest</code> argument refers to an array - * with a primitive component type. - * </ul> - * <p> - * Otherwise, if any of the following is true, an - * <code>IndexOutOfBoundsException</code> is - * thrown and the destination is not modified: - * <ul> - * <li>The <code>srcPos</code> argument is negative. - * <li>The <code>destPos</code> argument is negative. - * <li>The <code>length</code> argument is negative. - * <li><code>srcPos+length</code> is greater than - * <code>src.length</code>, the length of the source array. - * <li><code>destPos+length</code> is greater than - * <code>dest.length</code>, the length of the destination array. - * </ul> - * <p> - * Otherwise, if any actual component of the source array from - * position <code>srcPos</code> through - * <code>srcPos+length-1</code> cannot be converted to the component - * type of the destination array by assignment conversion, an - * <code>ArrayStoreException</code> is thrown. In this case, let - * <b><i>k</i></b> be the smallest nonnegative integer less than - * length such that <code>src[srcPos+</code><i>k</i><code>]</code> - * cannot be converted to the component type of the destination - * array; when the exception is thrown, source array components from - * positions <code>srcPos</code> through - * <code>srcPos+</code><i>k</i><code>-1</code> - * will already have been copied to destination array positions - * <code>destPos</code> through - * <code>destPos+</code><i>k</I><code>-1</code> and no other - * positions of the destination array will have been modified. - * (Because of the restrictions already itemized, this - * paragraph effectively applies only to the situation where both - * arrays have component types that are reference types.) - * - * @param src the source array. - * @param srcPos starting position in the source array. - * @param dest the destination array. - * @param destPos starting position in the destination data. - * @param length the number of array elements to be copied. - * @exception IndexOutOfBoundsException if copying would cause - * access of data outside array bounds. - * @exception ArrayStoreException if an element in the <code>src</code> - * array could not be stored into the <code>dest</code> array - * because of a type mismatch. - * @exception NullPointerException if either <code>src</code> or - * <code>dest</code> is <code>null</code>. - */ - public static native void arraycopy(Object src, int srcPos, - Object dest, int destPos, - int length); - - /** - * Returns the same hash code for the given object as - * would be returned by the default method hashCode(), - * whether or not the given object's class overrides - * hashCode(). - * The hash code for the null reference is zero. - * - * @param x object for which the hashCode is to be calculated - * @return the hashCode - * @since JDK1.1 - */ - public static int identityHashCode(Object x) { - return cli.System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(x); - } - - /** - * System properties. The following properties are guaranteed to be defined: - * <dl> - * <dt>java.version <dd>Java version number - * <dt>java.vendor <dd>Java vendor specific string - * <dt>java.vendor.url <dd>Java vendor URL - * <dt>java.home <dd>Java installation directory - * <dt>java.class.version <dd>Java class version number - * <dt>java.class.path <dd>Java classpath - * <dt>os.name <dd>Operating System Name - * <dt>os.arch <dd>Operating System Architecture - * <dt>os.version <dd>Operating System Version - * <dt>file.separator <dd>File separator ("/" on Unix) - * <dt>path.separator <dd>Path separator (":" on Unix) - * <dt>line.separator <dd>Line separator ("\n" on Unix) - * <dt>user.name <dd>User account name - * <dt>user.home <dd>User home directory - * <dt>user.dir <dd>User's current working directory - * </dl> - */ - - //private static native Properties initProperties(Properties props); - - /** - * Determines the current system properties. - * <p> - * First, if there is a security manager, its - * <code>checkPropertiesAccess</code> method is called with no - * arguments. This may result in a security exception. - * <p> - * The current set of system properties for use by the - * {@link #getProperty(String)} method is returned as a - * <code>Properties</code> object. If there is no current set of - * system properties, a set of system properties is first created and - * initialized. This set of system properties always includes values - * for the following keys: - * <table summary="Shows property keys and associated values"> - * <tr><th>Key</th> - * <th>Description of Associated Value</th></tr> - * <tr><td><code>java.version</code></td> - * <td>Java Runtime Environment version</td></tr> - * <tr><td><code>java.vendor</code></td> - * <td>Java Runtime Environment vendor</td></tr - * <tr><td><code>java.vendor.url</code></td> - * <td>Java vendor URL</td></tr> - * <tr><td><code>java.home</code></td> - * <td>Java installation directory</td></tr> - * <tr><td><code>java.vm.specification.version</code></td> - * <td>Java Virtual Machine specification version</td></tr> - * <tr><td><code>java.vm.specification.vendor</code></td> - * <td>Java Virtual Machine specification vendor</td></tr> - * <tr><td><code>java.vm.specification.name</code></td> - * <td>Java Virtual Machine specification name</td></tr> - * <tr><td><code>java.vm.version</code></td> - * <td>Java Virtual Machine implementation version</td></tr> - * <tr><td><code>java.vm.vendor</code></td> - * <td>Java Virtual Machine implementation vendor</td></tr> - * <tr><td><code>java.vm.name</code></td> - * <td>Java Virtual Machine implementation name</td></tr> - * <tr><td><code>java.specification.version</code></td> - * <td>Java Runtime Environment specification version</td></tr> - * <tr><td><code>java.specification.vendor</code></td> - * <td>Java Runtime Environment specification vendor</td></tr> - * <tr><td><code>java.specification.name</code></td> - * <td>Java Runtime Environment specification name</td></tr> - * <tr><td><code>java.class.version</code></td> - * <td>Java class format version number</td></tr> - * <tr><td><code>java.class.path</code></td> - * <td>Java class path</td></tr> - * <tr><td><code>java.library.path</code></td> - * <td>List of paths to search when loading libraries</td></tr> - * <tr><td><code>java.io.tmpdir</code></td> - * <td>Default temp file path</td></tr> - * <tr><td><code>java.compiler</code></td> - * <td>Name of JIT compiler to use</td></tr> - * <tr><td><code>java.ext.dirs</code></td> - * <td>Path of extension directory or directories</td></tr> - * <tr><td><code>os.name</code></td> - * <td>Operating system name</td></tr> - * <tr><td><code>os.arch</code></td> - * <td>Operating system architecture</td></tr> - * <tr><td><code>os.version</code></td> - * <td>Operating system version</td></tr> - * <tr><td><code>file.separator</code></td> - * <td>File separator ("/" on UNIX)</td></tr> - * <tr><td><code>path.separator</code></td> - * <td>Path separator (":" on UNIX)</td></tr> - * <tr><td><code>line.separator</code></td> - * <td>Line separator ("\n" on UNIX)</td></tr> - * <tr><td><code>user.name</code></td> - * <td>User's account name</td></tr> - * <tr><td><code>user.home</code></td> - * <td>User's home directory</td></tr> - * <tr><td><code>user.dir</code></td> - * <td>User's current working directory</td></tr> - * </table> - * <p> - * Multiple paths in a system property value are separated by the path - * separator character of the platform. - * <p> - * Note that even if the security manager does not permit the - * <code>getProperties</code> operation, it may choose to permit the - * {@link #getProperty(String)} operation. - * - * @return the system properties - * @exception SecurityException if a security manager exists and its - * <code>checkPropertiesAccess</code> method doesn't allow access - * to the system properties. - * @see #setProperties - * @see java.lang.SecurityException - * @see java.lang.SecurityManager#checkPropertiesAccess() - * @see java.util.Properties - */ - public static Properties getProperties() { - SecurityManager sm = getSecurityManager(); - if (sm != null) { - sm.checkPropertiesAccess(); - } - - return Props.props; - } - - /** - * Returns the system-dependent line separator string. It always - * returns the same value - the initial value of the {@linkplain - * #getProperty(String) system property} {@code line.separator}. - * - * <p>On UNIX systems, it returns {@code "\n"}; on Microsoft - * Windows systems it returns {@code "\r\n"}. - */ - public static String lineSeparator() { - return Props.lineSeparator; - } - - /** - * Sets the system properties to the <code>Properties</code> - * argument. - * <p> - * First, if there is a security manager, its - * <code>checkPropertiesAccess</code> method is called with no - * arguments. This may result in a security exception. - * <p> - * The argument becomes the current set of system properties for use - * by the {@link #getProperty(String)} method. If the argument is - * <code>null</code>, then the current set of system properties is - * forgotten. - * - * @param props the new system properties. - * @exception SecurityException if a security manager exists and its - * <code>checkPropertiesAccess</code> method doesn't allow access - * to the system properties. - * @see #getProperties - * @see java.util.Properties - * @see java.lang.SecurityException - * @see java.lang.SecurityManager#checkPropertiesAccess() - */ - public static void setProperties(Properties props) { - SecurityManager sm = getSecurityManager(); - if (sm != null) { - sm.checkPropertiesAccess(); - } - if (props == null) { - props = new Properties(); - VMSystemProperties.initProperties(props); - } - Props.props = props; - } - - /** - * Gets the system property indicated by the specified key. - * <p> - * First, if there is a security manager, its - * <code>checkPropertyAccess</code> method is called with the key as - * its argument. This may result in a SecurityException. - * <p> - * If there is no current set of system properties, a set of system - * properties is first created and initialized in the same manner as - * for the <code>getProperties</code> method. - * - * @param key the name of the system property. - * @return the string value of the system property, - * or <code>null</code> if there is no property with that key. - * - * @exception SecurityException if a security manager exists and its - * <code>checkPropertyAccess</code> method doesn't allow - * access to the specified system property. - * @exception NullPointerException if <code>key</code> is - * <code>null</code>. - * @exception IllegalArgumentException if <code>key</code> is empty. - * @see #setProperty - * @see java.lang.SecurityException - * @see java.lang.SecurityManager#checkPropertyAccess(java.lang.String) - * @see java.lang.System#getProperties() - */ - public static String getProperty(String key) { - checkKey(key); - SecurityManager sm = getSecurityManager(); - if (sm != null) { - sm.checkPropertyAccess(key); - } - - return Props.props.getProperty(key); - } - - /** - * Gets the system property indicated by the specified key. - * <p> - * First, if there is a security manager, its - * <code>checkPropertyAccess</code> method is called with the - * <code>key</code> as its argument. - * <p> - * If there is no current set of system properties, a set of system - * properties is first created and initialized in the same manner as - * for the <code>getProperties</code> method. - * - * @param key the name of the system property. - * @param def a default value. - * @return the string value of the system property, - * or the default value if there is no property with that key. - * - * @exception SecurityException if a security manager exists and its - * <code>checkPropertyAccess</code> method doesn't allow - * access to the specified system property. - * @exception NullPointerException if <code>key</code> is - * <code>null</code>. - * @exception IllegalArgumentException if <code>key</code> is empty. - * @see #setProperty - * @see java.lang.SecurityManager#checkPropertyAccess(java.lang.String) - * @see java.lang.System#getProperties() - */ - public static String getProperty(String key, String def) { - checkKey(key); - SecurityManager sm = getSecurityManager(); - if (sm != null) { - sm.checkPropertyAccess(key); - } - - return Props.props.getProperty(key, def); - } - - /** - * Sets the system property indicated by the specified key. - * <p> - * First, if a security manager exists, its - * <code>SecurityManager.checkPermission</code> method - * is called with a <code>PropertyPermission(key, "write")</code> - * permission. This may result in a SecurityException being thrown. - * If no exception is thrown, the specified property is set to the given - * value. - * <p> - * - * @param key the name of the system property. - * @param value the value of the system property. - * @return the previous value of the system property, - * or <code>null</code> if it did not have one. - * - * @exception SecurityException if a security manager exists and its - * <code>checkPermission</code> method doesn't allow - * setting of the specified property. - * @exception NullPointerException if <code>key</code> or - * <code>value</code> is <code>null</code>. - * @exception IllegalArgumentException if <code>key</code> is empty. - * @see #getProperty - * @see java.lang.System#getProperty(java.lang.String) - * @see java.lang.System#getProperty(java.lang.String, java.lang.String) - * @see java.util.PropertyPermission - * @see SecurityManager#checkPermission - * @since 1.2 - */ - public static String setProperty(String key, String value) { - checkKey(key); - SecurityManager sm = getSecurityManager(); - if (sm != null) { - sm.checkPermission(new PropertyPermission(key, - SecurityConstants.PROPERTY_WRITE_ACTION)); - } - - return (String) Props.props.setProperty(key, value); - } - - /** - * Removes the system property indicated by the specified key. - * <p> - * First, if a security manager exists, its - * <code>SecurityManager.checkPermission</code> method - * is called with a <code>PropertyPermission(key, "write")</code> - * permission. This may result in a SecurityException being thrown. - * If no exception is thrown, the specified property is removed. - * <p> - * - * @param key the name of the system property to be removed. - * @return the previous string value of the system property, - * or <code>null</code> if there was no property with that key. - * - * @exception SecurityException if a security manager exists and its - * <code>checkPropertyAccess</code> method doesn't allow - * access to the specified system property. - * @exception NullPointerException if <code>key</code> is - * <code>null</code>. - * @exception IllegalArgumentException if <code>key</code> is empty. - * @see #getProperty - * @see #setProperty - * @see java.util.Properties - * @see java.lang.SecurityException - * @see java.lang.SecurityManager#checkPropertiesAccess() - * @since 1.5 - */ - public static String clearProperty(String key) { - checkKey(key); - SecurityManager sm = getSecurityManager(); - if (sm != null) { - sm.checkPermission(new PropertyPermission(key, "write")); - } - - return (String) Props.props.remove(key); - } - - private static void checkKey(String key) { - if (key == null) { - throw new NullPointerException("key can't be null"); - } - if (key.equals("")) { - throw new IllegalArgumentException("key can't be empty"); - } - } - - /** - * Gets the value of the specified environment variable. An - * environment variable is a system-dependent external named - * value. - * - * <p>If a security manager exists, its - * {@link SecurityManager#checkPermission checkPermission} - * method is called with a - * <code>{@link RuntimePermission}("getenv."+name)</code> - * permission. This may result in a {@link SecurityException} - * being thrown. If no exception is thrown the value of the - * variable <code>name</code> is returned. - * - * <p><a name="EnvironmentVSSystemProperties"><i>System - * properties</i> and <i>environment variables</i></a> are both - * conceptually mappings between names and values. Both - * mechanisms can be used to pass user-defined information to a - * Java process. Environment variables have a more global effect, - * because they are visible to all descendants of the process - * which defines them, not just the immediate Java subprocess. - * They can have subtly different semantics, such as case - * insensitivity, on different operating systems. For these - * reasons, environment variables are more likely to have - * unintended side effects. It is best to use system properties - * where possible. Environment variables should be used when a - * global effect is desired, or when an external system interface - * requires an environment variable (such as <code>PATH</code>). - * - * <p>On UNIX systems the alphabetic case of <code>name</code> is - * typically significant, while on Microsoft Windows systems it is - * typically not. For example, the expression - * <code>System.getenv("FOO").equals(System.getenv("foo"))</code> - * is likely to be true on Microsoft Windows. - * - * @param name the name of the environment variable - * @return the string value of the variable, or <code>null</code> - * if the variable is not defined in the system environment - * @throws NullPointerException if <code>name</code> is <code>null</code> - * @throws SecurityException - * if a security manager exists and its - * {@link SecurityManager#checkPermission checkPermission} - * method doesn't allow access to the environment variable - * <code>name</code> - * @see #getenv() - * @see ProcessBuilder#environment() - */ - public static String getenv(String name) { - SecurityManager sm = getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("getenv."+name)); - } - - return ProcessEnvironment.getenv(name); - } - - - /** - * Returns an unmodifiable string map view of the current system environment. - * The environment is a system-dependent mapping from names to - * values which is passed from parent to child processes. - * - * <p>If the system does not support environment variables, an - * empty map is returned. - * - * <p>The returned map will never contain null keys or values. - * Attempting to query the presence of a null key or value will - * throw a {@link NullPointerException}. Attempting to query - * the presence of a key or value which is not of type - * {@link String} will throw a {@link ClassCastException}. - * - * <p>The returned map and its collection views may not obey the - * general contract of the {@link Object#equals} and - * {@link Object#hashCode} methods. - * - * <p>The returned map is typically case-sensitive on all platforms. - * - * <p>If a security manager exists, its - * {@link SecurityManager#checkPermission checkPermission} - * method is called with a - * <code>{@link RuntimePermission}("getenv.*")</code> - * permission. This may result in a {@link SecurityException} being - * thrown. - * - * <p>When passing information to a Java subprocess, - * <a href=#EnvironmentVSSystemProperties>system properties</a> - * are generally preferred over environment variables. - * - * @return the environment as a map of variable names to values - * @throws SecurityException - * if a security manager exists and its - * {@link SecurityManager#checkPermission checkPermission} - * method doesn't allow access to the process environment - * @see #getenv(String) - * @see ProcessBuilder#environment() - * @since 1.5 - */ - public static java.util.Map<String,String> getenv() { - SecurityManager sm = getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("getenv.*")); - } - - return ProcessEnvironment.getenv(); - } - - /** - * Terminates the currently running Java Virtual Machine. The - * argument serves as a status code; by convention, a nonzero status - * code indicates abnormal termination. - * <p> - * This method calls the <code>exit</code> method in class - * <code>Runtime</code>. This method never returns normally. - * <p> - * The call <code>System.exit(n)</code> is effectively equivalent to - * the call: - * <blockquote><pre> - * Runtime.getRuntime().exit(n) - * </pre></blockquote> - * - * @param status exit status. - * @throws SecurityException - * if a security manager exists and its <code>checkExit</code> - * method doesn't allow exit with the specified status. - * @see java.lang.Runtime#exit(int) - */ - public static void exit(int status) { - Runtime.getRuntime().exit(status); - } - - /** - * Runs the garbage collector. - * <p> - * Calling the <code>gc</code> method suggests that the Java Virtual - * Machine expend effort toward recycling unused objects in order to - * make the memory they currently occupy available for quick reuse. - * When control returns from the method call, the Java Virtual - * Machine has made a best effort to reclaim space from all discarded - * objects. - * <p> - * The call <code>System.gc()</code> is effectively equivalent to the - * call: - * <blockquote><pre> - * Runtime.getRuntime().gc() - * </pre></blockquote> - * - * @see java.lang.Runtime#gc() - */ - public static void gc() { - Runtime.getRuntime().gc(); - } - - /** - * Runs the finalization methods of any objects pending finalization. - * <p> - * Calling this method suggests that the Java Virtual Machine expend - * effort toward running the <code>finalize</code> methods of objects - * that have been found to be discarded but whose <code>finalize</code> - * methods have not yet been run. When control returns from the - * method call, the Java Virtual Machine has made a best effort to - * complete all outstanding finalizations. - * <p> - * The call <code>System.runFinalization()</code> is effectively - * equivalent to the call: - * <blockquote><pre> - * Runtime.getRuntime().runFinalization() - * </pre></blockquote> - * - * @see java.lang.Runtime#runFinalization() - */ - public static void runFinalization() { - Runtime.getRuntime().runFinalization(); - } - - /** - * Enable or disable finalization on exit; doing so specifies that the - * finalizers of all objects that have finalizers that have not yet been - * automatically invoked are to be run before the Java runtime exits. - * By default, finalization on exit is disabled. - * - * <p>If there is a security manager, - * its <code>checkExit</code> method is first called - * with 0 as its argument to ensure the exit is allowed. - * This could result in a SecurityException. - * - * @deprecated This method is inherently unsafe. It may result in - * finalizers being called on live objects while other threads are - * concurrently manipulating those objects, resulting in erratic - * behavior or deadlock. - * @param value indicating enabling or disabling of finalization - * @throws SecurityException - * if a security manager exists and its <code>checkExit</code> - * method doesn't allow the exit. - * - * @see java.lang.Runtime#exit(int) - * @see java.lang.Runtime#gc() - * @see java.lang.SecurityManager#checkExit(int) - * @since JDK1.1 - */ - @Deprecated - public static void runFinalizersOnExit(boolean value) { - Runtime.getRuntime().runFinalizersOnExit(value); - } - - /** - * Loads a code file with the specified filename from the local file - * system as a dynamic library. The filename - * argument must be a complete path name. - * <p> - * The call <code>System.load(name)</code> is effectively equivalent - * to the call: - * <blockquote><pre> - * Runtime.getRuntime().load(name) - * </pre></blockquote> - * - * @param filename the file to load. - * @exception SecurityException if a security manager exists and its - * <code>checkLink</code> method doesn't allow - * loading of the specified dynamic library - * @exception UnsatisfiedLinkError if the file does not exist. - * @exception NullPointerException if <code>filename</code> is - * <code>null</code> - * @see java.lang.Runtime#load(java.lang.String) - * @see java.lang.SecurityManager#checkLink(java.lang.String) - */ - @CallerSensitive - public static void load(String filename) { - Runtime.getRuntime().load0(Reflection.getCallerClass(), filename); - } - - /** - * Loads the system library specified by the <code>libname</code> - * argument. The manner in which a library name is mapped to the - * actual system library is system dependent. - * <p> - * The call <code>System.loadLibrary(name)</code> is effectively - * equivalent to the call - * <blockquote><pre> - * Runtime.getRuntime().loadLibrary(name) - * </pre></blockquote> - * - * @param libname the name of the library. - * @exception SecurityException if a security manager exists and its - * <code>checkLink</code> method doesn't allow - * loading of the specified dynamic library - * @exception UnsatisfiedLinkError if the library does not exist. - * @exception NullPointerException if <code>libname</code> is - * <code>null</code> - * @see java.lang.Runtime#loadLibrary(java.lang.String) - * @see java.lang.SecurityManager#checkLink(java.lang.String) - */ - @CallerSensitive - public static void loadLibrary(String libname) { - Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname); - } - - /** - * Maps a library name into a platform-specific string representing - * a native library. - * - * @param libname the name of the library. - * @return a platform-dependent native library name. - * @exception NullPointerException if <code>libname</code> is - * <code>null</code> - * @see java.lang.System#loadLibrary(java.lang.String) - * @see java.lang.ClassLoader#findLibrary(java.lang.String) - * @since 1.2 - */ - public static String mapLibraryName(String libname) { - if (libname == null) { - throw new NullPointerException(); - } - if (ikvm.internal.Util.WINDOWS) { - return libname + ".dll"; - } else if (ikvm.internal.Util.MACOSX) { - return "lib" + libname + ".jnilib"; - } else { - return "lib" + libname + ".so"; - } - } - /* returns the class of the caller. */ - static Class<?> getCallerClass() { - // NOTE use of more generic Reflection.getCallerClass() - return Reflection.getCallerClass(3); - } -} diff --git a/openjdk/java/lang/Thread.java b/openjdk/java/lang/Thread.java deleted file mode 100644 index 0ed60578..00000000 --- a/openjdk/java/lang/Thread.java +++ /dev/null @@ -1,2598 +0,0 @@ -/* - * Copyright (c) 1994, 2013, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang; - -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.security.AccessController; -import java.security.AccessControlContext; -import java.security.PrivilegedAction; -import java.util.Map; -import java.util.HashMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.locks.LockSupport; -import sun.nio.ch.Interruptible; -import sun.reflect.CallerSensitive; -import sun.reflect.Reflection; -import sun.security.util.SecurityConstants; - - -/** - * A <i>thread</i> is a thread of execution in a program. The Java - * Virtual Machine allows an application to have multiple threads of - * execution running concurrently. - * <p> - * Every thread has a priority. Threads with higher priority are - * executed in preference to threads with lower priority. Each thread - * may or may not also be marked as a daemon. When code running in - * some thread creates a new <code>Thread</code> object, the new - * thread has its priority initially set equal to the priority of the - * creating thread, and is a daemon thread if and only if the - * creating thread is a daemon. - * <p> - * When a Java Virtual Machine starts up, there is usually a single - * non-daemon thread (which typically calls the method named - * <code>main</code> of some designated class). The Java Virtual - * Machine continues to execute threads until either of the following - * occurs: - * <ul> - * <li>The <code>exit</code> method of class <code>Runtime</code> has been - * called and the security manager has permitted the exit operation - * to take place. - * <li>All threads that are not daemon threads have died, either by - * returning from the call to the <code>run</code> method or by - * throwing an exception that propagates beyond the <code>run</code> - * method. - * </ul> - * <p> - * There are two ways to create a new thread of execution. One is to - * declare a class to be a subclass of <code>Thread</code>. This - * subclass should override the <code>run</code> method of class - * <code>Thread</code>. An instance of the subclass can then be - * allocated and started. For example, a thread that computes primes - * larger than a stated value could be written as follows: - * <hr><blockquote><pre> - * class PrimeThread extends Thread { - * long minPrime; - * PrimeThread(long minPrime) { - * this.minPrime = minPrime; - * } - * - * public void run() { - * // compute primes larger than minPrime - * . . . - * } - * } - * </pre></blockquote><hr> - * <p> - * The following code would then create a thread and start it running: - * <blockquote><pre> - * PrimeThread p = new PrimeThread(143); - * p.start(); - * </pre></blockquote> - * <p> - * The other way to create a thread is to declare a class that - * implements the <code>Runnable</code> interface. That class then - * implements the <code>run</code> method. An instance of the class can - * then be allocated, passed as an argument when creating - * <code>Thread</code>, and started. The same example in this other - * style looks like the following: - * <hr><blockquote><pre> - * class PrimeRun implements Runnable { - * long minPrime; - * PrimeRun(long minPrime) { - * this.minPrime = minPrime; - * } - * - * public void run() { - * // compute primes larger than minPrime - * . . . - * } - * } - * </pre></blockquote><hr> - * <p> - * The following code would then create a thread and start it running: - * <blockquote><pre> - * PrimeRun p = new PrimeRun(143); - * new Thread(p).start(); - * </pre></blockquote> - * <p> - * Every thread has a name for identification purposes. More than - * one thread may have the same name. If a name is not specified when - * a thread is created, a new name is generated for it. - * <p> - * Unless otherwise noted, passing a {@code null} argument to a constructor - * or method in this class will cause a {@link NullPointerException} to be - * thrown. - * - * @author unascribed - * @see Runnable - * @see Runtime#exit(int) - * @see #run() - * @see #stop() - * @since JDK1.0 - */ -public -class Thread implements Runnable { - // [IKVM] - static { - // force the set/getContextClassLoader methods to be JIT compiled, because isCCLOverridden(Thread) depends on it - // (we don't want to use RuntimeHelpers.PrepareMethod() because it requires full trust) - Thread dummy = new Thread((Void)null); - dummy.getContextClassLoader(); - dummy.setContextClassLoader(ClassLoader.DUMMY); - } - private Thread(Void _) { - // body replaced in map.xml - } - final class Cleanup { - private final Thread thread; - - Cleanup(Thread thread) { - this.thread = thread; - } - - protected void finalize() { - thread.die(); - } - } - /* --- start IKVM specific state --- */ - static final int[] nonDaemonCount = new int[1]; - @cli.System.ThreadStaticAttribute.Annotation - static Thread current; - @cli.System.ThreadStaticAttribute.Annotation - private static Cleanup cleanup; - private final Object lock = new Object(); - private cli.System.Threading.Thread nativeThread; - private Throwable stillborn; - private boolean running; // used only for coordination with stop0(), is never set to false - private volatile boolean interruptPending; - private volatile boolean nativeInterruptPending; - private volatile boolean interruptableWait; - private boolean timedWait; - volatile Object parkLock; // used by get/setParkLock in map.xml - int parkState; // used by cmpxchgParkState in map.xml - /* --- end IKVM specific state --- */ - - private volatile char name[]; - private int priority; - private Thread threadQ; - private long eetop; - - /* Whether or not to single_step this thread. */ - private boolean single_step; - - /* Whether or not the thread is a daemon thread. */ - private boolean daemon = false; - - /* What will be run. */ - private Runnable target; - - /* The group of this thread */ - private ThreadGroup group; - - /* The context ClassLoader for this thread */ - private volatile ClassLoader contextClassLoader; - - /* The inherited AccessControlContext of this thread */ - /* [IKVM] this contains either an AccessControlContext or an AccessController.LazyContext */ - Object inheritedAccessControlContext; - - /* For autonumbering anonymous threads. */ - private static int threadInitNumber; - private static synchronized int nextThreadNum() { - return threadInitNumber++; - } - - /* ThreadLocal values pertaining to this thread. This map is maintained - * by the ThreadLocal class. */ - ThreadLocal.ThreadLocalMap threadLocals = null; - - /* - * InheritableThreadLocal values pertaining to this thread. This map is - * maintained by the InheritableThreadLocal class. - */ - ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; - - /* - * The requested stack size for this thread, or 0 if the creator did - * not specify a stack size. It is up to the VM to do whatever it - * likes with this number; some VMs will ignore it. - */ - private long stackSize; - - /* - * JVM-private state that persists after native thread termination. - */ - private long nativeParkEventPointer; - - /* - * Thread ID - */ - private long tid; - - /* For generating thread ID */ - private static long threadSeqNumber; - - /* Java thread status for tools, - * initialized to indicate thread 'not yet started' - */ - - private volatile int threadStatus = 0; - - - private static synchronized long nextThreadID() { - return ++threadSeqNumber; - } - - /** - * The argument supplied to the current call to - * java.util.concurrent.locks.LockSupport.park. - * Set by (private) java.util.concurrent.locks.LockSupport.setBlocker - * Accessed using java.util.concurrent.locks.LockSupport.getBlocker - */ - @ikvm.lang.Internal // [IKVM] accessed from java.util.concurrent - public volatile Object parkBlocker; - - /* The object in which this thread is blocked in an interruptible I/O - * operation, if any. The blocker's interrupt method should be invoked - * after setting this thread's interrupt status. - */ - private volatile Interruptible blocker; - private final Object blockerLock = new Object(); - - /* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code - */ - void blockedOn(Interruptible b) { - synchronized (blockerLock) { - blocker = b; - } - } - - /** - * The minimum priority that a thread can have. - */ - public final static int MIN_PRIORITY = 1; - - /** - * The default priority that is assigned to a thread. - */ - public final static int NORM_PRIORITY = 5; - - /** - * The maximum priority that a thread can have. - */ - public final static int MAX_PRIORITY = 10; - - /** - * Returns a reference to the currently executing thread object. - * - * @return the currently executing thread. - */ - public static Thread currentThread() { - Thread c = current; - if (c == null) { - c = new Thread(getMainThreadGroup()); - } - return c; - } - - private static native ThreadGroup getMainThreadGroup(); - - /** - * A hint to the scheduler that the current thread is willing to yield - * its current use of a processor. The scheduler is free to ignore this - * hint. - * - * <p> Yield is a heuristic attempt to improve relative progression - * between threads that would otherwise over-utilise a CPU. Its use - * should be combined with detailed profiling and benchmarking to - * ensure that it actually has the desired effect. - * - * <p> It is rarely appropriate to use this method. It may be useful - * for debugging or testing purposes, where it may help to reproduce - * bugs due to race conditions. It may also be useful when designing - * concurrency control constructs such as the ones in the - * {@link java.util.concurrent.locks} package. - */ - public static void yield() { - cli.System.Threading.Thread.Sleep(0); - } - - private void enterInterruptableWait(boolean timedWait) throws InterruptedException { - synchronized (lock) { - if (interruptPending) { - interruptPending = false; - throw new InterruptedException(); - } - interruptableWait = true; - this.timedWait = timedWait; - } - } - - private void leaveInterruptableWait() throws InterruptedException { - cli.System.Threading.ThreadInterruptedException dotnetInterrupt = null; - interruptableWait = false; - for (; ; ) { - try { - if (false) throw new cli.System.Threading.ThreadInterruptedException(); - synchronized (lock) { - if (nativeInterruptPending) { - nativeInterruptPending = false; - // HACK if there is a pending Interrupt (on the .NET thread), we need to consume that - // (if there was no contention on "lock (this)" above the interrupted state isn't checked) - try { - if (false) throw new cli.System.Threading.ThreadInterruptedException(); - cli.System.Threading.Thread t = cli.System.Threading.Thread.get_CurrentThread(); - // the obvious thing to do would be t.Interrupt() / t.Join(), - // but for some reason that causes a regression in JSR166TestCase (probably a CLR bug) - // so we waste a time slice... sigh. - t.Join(1); - } - catch (cli.System.Threading.ThreadInterruptedException _) { - } - } - if (interruptPending) { - interruptPending = false; - throw new InterruptedException(); - } - } - break; - } - catch (cli.System.Threading.ThreadInterruptedException x) { - dotnetInterrupt = x; - nativeInterruptPending = false; - } - } - if (dotnetInterrupt != null) { - ikvm.runtime.Util.throwException(dotnetInterrupt); - } - } - - /** - * Causes the currently executing thread to sleep (temporarily cease - * execution) for the specified number of milliseconds, subject to - * the precision and accuracy of system timers and schedulers. The thread - * does not lose ownership of any monitors. - * - * @param millis - * the length of time to sleep in milliseconds - * - * @throws IllegalArgumentException - * if the value of {@code millis} is negative - * - * @throws InterruptedException - * if any thread has interrupted the current thread. The - * <i>interrupted status</i> of the current thread is - * cleared when this exception is thrown. - */ - public static void sleep(long millis) throws InterruptedException { - if (millis < 0) { - throw new IllegalArgumentException("timeout value is negative"); - } - Thread c = currentThread(); - c.enterInterruptableWait(true); - try { - if (false) throw new cli.System.Threading.ThreadInterruptedException(); - for (long iter = millis / Integer.MAX_VALUE; iter != 0; iter--) - { - cli.System.Threading.Thread.Sleep(Integer.MAX_VALUE); - } - cli.System.Threading.Thread.Sleep((int)(millis % Integer.MAX_VALUE)); - } - catch (cli.System.Threading.ThreadInterruptedException _) { - } - finally { - c.leaveInterruptableWait(); - } - } - - /** - * Causes the currently executing thread to sleep (temporarily cease - * execution) for the specified number of milliseconds plus the specified - * number of nanoseconds, subject to the precision and accuracy of system - * timers and schedulers. The thread does not lose ownership of any - * monitors. - * - * @param millis - * the length of time to sleep in milliseconds - * - * @param nanos - * {@code 0-999999} additional nanoseconds to sleep - * - * @throws IllegalArgumentException - * if the value of {@code millis} is negative, or the value of - * {@code nanos} is not in the range {@code 0-999999} - * - * @throws InterruptedException - * if any thread has interrupted the current thread. The - * <i>interrupted status</i> of the current thread is - * cleared when this exception is thrown. - */ - public static void sleep(long millis, int nanos) - throws InterruptedException { - if (millis < 0) { - throw new IllegalArgumentException("timeout value is negative"); - } - - if (nanos < 0 || nanos > 999999) { - throw new IllegalArgumentException( - "nanosecond timeout value out of range"); - } - - if (nanos >= 500000 || (nanos != 0 && millis == 0)) { - millis++; - } - - sleep(millis); - } - - /** - * Initializes a Thread with the current AccessControlContext. - * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext) - */ - private void init(ThreadGroup g, Runnable target, String name, - long stackSize) { - init(g, target, name, stackSize, null); - } - - /** - * Initializes a Thread. - * - * @param g the Thread group - * @param target the object whose run() method gets called - * @param name the name of the new Thread - * @param stackSize the desired stack size for the new thread, or - * zero to indicate that this parameter is to be ignored. - * @param acc the AccessControlContext to inherit, or - * AccessController.getContext() if null - */ - private void init(ThreadGroup g, Runnable target, String name, - long stackSize, AccessControlContext acc) { - if (name == null) { - throw new NullPointerException("name cannot be null"); - } - - this.name = name.toCharArray(); - - Thread parent = currentThread(); - SecurityManager security = System.getSecurityManager(); - if (g == null) { - /* Determine if it's an applet or not */ - - /* If there is a security manager, ask the security manager - what to do. */ - if (security != null) { - g = security.getThreadGroup(); - } - - /* If the security doesn't have a strong opinion of the matter - use the parent thread group. */ - if (g == null) { - g = parent.getThreadGroup(); - } - } - - /* checkAccess regardless of whether or not threadgroup is - explicitly passed in. */ - g.checkAccess(); - - /* - * Do we have the required permissions? - */ - if (security != null) { - if (isCCLOverridden(this)) { - security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); - } - } - - g.addUnstarted(); - - this.group = g; - this.daemon = parent.isDaemon(); - this.priority = parent.getPriority(); - if (isCCLOverridden(parent)) - this.contextClassLoader = parent.getContextClassLoader(); - else - this.contextClassLoader = parent.contextClassLoader; - this.inheritedAccessControlContext = - acc != null ? acc : AccessController.getLazyContext(parent.inheritedAccessControlContext); - this.target = target; - setPriority(priority); - if (parent.inheritableThreadLocals != null) - this.inheritableThreadLocals = - ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); - /* Stash the specified stack size in case the VM cares */ - this.stackSize = stackSize; - - /* Set thread ID */ - tid = nextThreadID(); - } - - // [IKVM] constructor for attaching to a .NET thread - Thread(ThreadGroup g) { - this.running = true; - cli.System.Threading.Thread thread = cli.System.Threading.Thread.get_CurrentThread(); - nativeThread = thread; - String name = thread.get_Name(); - if (name == null) { - name = "Thread-" + nextThreadNum(); - } - - this.group = g; - this.daemon = thread.get_IsBackground(); - this.priority = mapClrPriorityToJava(thread.get_Priority().Value); - this.name = name.toCharArray(); - this.contextClassLoader = ClassLoader.DUMMY; - this.threadStatus = 0x0005; /* JVMTI_THREAD_STATE_ALIVE + JVMTI_THREAD_STATE_RUNNABLE */ - - /* Set thread ID */ - tid = nextThreadID(); - - synchronized (g) { - g.addUnstarted(); - g.add(this); - } - - current = this; - cleanup = new Cleanup(this); - - if (!daemon) { - cli.System.Threading.Interlocked.Increment(nonDaemonCount); - } - } - - private static int mapClrPriorityToJava(int priority) { - // TODO consider supporting -XX:JavaPriorityX_To_OSPriority settings - switch (priority) { - case cli.System.Threading.ThreadPriority.Lowest: - return MIN_PRIORITY; - case cli.System.Threading.ThreadPriority.BelowNormal: - return 3; - default: - case cli.System.Threading.ThreadPriority.Normal: - return NORM_PRIORITY; - case cli.System.Threading.ThreadPriority.AboveNormal: - return 7; - case cli.System.Threading.ThreadPriority.Highest: - return MAX_PRIORITY; - } - } - - private static int mapJavaPriorityToClr(int priority) { - // TODO consider supporting -XX:JavaPriorityX_To_OSPriority settings - if (priority == MIN_PRIORITY) { - return cli.System.Threading.ThreadPriority.Lowest; - } - else if (priority > Thread.MIN_PRIORITY && priority < Thread.NORM_PRIORITY) { - return cli.System.Threading.ThreadPriority.BelowNormal; - } - else if (priority == Thread.NORM_PRIORITY) { - return cli.System.Threading.ThreadPriority.Normal; - } - else if (priority > Thread.NORM_PRIORITY && priority < Thread.MAX_PRIORITY) { - return cli.System.Threading.ThreadPriority.AboveNormal; - } - else if (priority == Thread.MAX_PRIORITY) { - return cli.System.Threading.ThreadPriority.Highest; - } - else { - // can't happen - return cli.System.Threading.ThreadPriority.Normal; - } - } - - /** - * Throws CloneNotSupportedException as a Thread can not be meaningfully - * cloned. Construct a new Thread instead. - * - * @throws CloneNotSupportedException - * always - */ - @Override - protected Object clone() throws CloneNotSupportedException { - throw new CloneNotSupportedException(); - } - - /** - * Allocates a new {@code Thread} object. This constructor has the same - * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} - * {@code (null, null, gname)}, where {@code gname} is a newly generated - * name. Automatically generated names are of the form - * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer. - */ - public Thread() { - init(null, null, "Thread-" + nextThreadNum(), 0); - } - - /** - * Allocates a new {@code Thread} object. This constructor has the same - * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} - * {@code (null, target, gname)}, where {@code gname} is a newly generated - * name. Automatically generated names are of the form - * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer. - * - * @param target - * the object whose {@code run} method is invoked when this thread - * is started. If {@code null}, this classes {@code run} method does - * nothing. - */ - public Thread(Runnable target) { - init(null, target, "Thread-" + nextThreadNum(), 0); - } - - /** - * Creates a new Thread that inherits the given AccessControlContext. - * This is not a public constructor. - */ - Thread(Runnable target, AccessControlContext acc) { - init(null, target, "Thread-" + nextThreadNum(), 0, acc); - } - - /** - * Allocates a new {@code Thread} object. This constructor has the same - * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} - * {@code (group, target, gname)} ,where {@code gname} is a newly generated - * name. Automatically generated names are of the form - * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer. - * - * @param group - * the thread group. If {@code null} and there is a security - * manager, the group is determined by {@linkplain - * SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. - * If there is not a security manager or {@code - * SecurityManager.getThreadGroup()} returns {@code null}, the group - * is set to the current thread's thread group. - * - * @param target - * the object whose {@code run} method is invoked when this thread - * is started. If {@code null}, this thread's run method is invoked. - * - * @throws SecurityException - * if the current thread cannot create a thread in the specified - * thread group - */ - public Thread(ThreadGroup group, Runnable target) { - init(group, target, "Thread-" + nextThreadNum(), 0); - } - - /** - * Allocates a new {@code Thread} object. This constructor has the same - * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} - * {@code (null, null, name)}. - * - * @param name - * the name of the new thread - */ - public Thread(String name) { - init(null, null, name, 0); - } - - /** - * Allocates a new {@code Thread} object. This constructor has the same - * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} - * {@code (group, null, name)}. - * - * @param group - * the thread group. If {@code null} and there is a security - * manager, the group is determined by {@linkplain - * SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. - * If there is not a security manager or {@code - * SecurityManager.getThreadGroup()} returns {@code null}, the group - * is set to the current thread's thread group. - * - * @param name - * the name of the new thread - * - * @throws SecurityException - * if the current thread cannot create a thread in the specified - * thread group - */ - public Thread(ThreadGroup group, String name) { - init(group, null, name, 0); - } - - /** - * Allocates a new {@code Thread} object. This constructor has the same - * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} - * {@code (null, target, name)}. - * - * @param target - * the object whose {@code run} method is invoked when this thread - * is started. If {@code null}, this thread's run method is invoked. - * - * @param name - * the name of the new thread - */ - public Thread(Runnable target, String name) { - init(null, target, name, 0); - } - - /** - * Allocates a new {@code Thread} object so that it has {@code target} - * as its run object, has the specified {@code name} as its name, - * and belongs to the thread group referred to by {@code group}. - * - * <p>If there is a security manager, its - * {@link SecurityManager#checkAccess(ThreadGroup) checkAccess} - * method is invoked with the ThreadGroup as its argument. - * - * <p>In addition, its {@code checkPermission} method is invoked with - * the {@code RuntimePermission("enableContextClassLoaderOverride")} - * permission when invoked directly or indirectly by the constructor - * of a subclass which overrides the {@code getContextClassLoader} - * or {@code setContextClassLoader} methods. - * - * <p>The priority of the newly created thread is set equal to the - * priority of the thread creating it, that is, the currently running - * thread. The method {@linkplain #setPriority setPriority} may be - * used to change the priority to a new value. - * - * <p>The newly created thread is initially marked as being a daemon - * thread if and only if the thread creating it is currently marked - * as a daemon thread. The method {@linkplain #setDaemon setDaemon} - * may be used to change whether or not a thread is a daemon. - * - * @param group - * the thread group. If {@code null} and there is a security - * manager, the group is determined by {@linkplain - * SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. - * If there is not a security manager or {@code - * SecurityManager.getThreadGroup()} returns {@code null}, the group - * is set to the current thread's thread group. - * - * @param target - * the object whose {@code run} method is invoked when this thread - * is started. If {@code null}, this thread's run method is invoked. - * - * @param name - * the name of the new thread - * - * @throws SecurityException - * if the current thread cannot create a thread in the specified - * thread group or cannot override the context class loader methods. - */ - public Thread(ThreadGroup group, Runnable target, String name) { - init(group, target, name, 0); - } - - /** - * Allocates a new {@code Thread} object so that it has {@code target} - * as its run object, has the specified {@code name} as its name, - * and belongs to the thread group referred to by {@code group}, and has - * the specified <i>stack size</i>. - * - * <p>This constructor is identical to {@link - * #Thread(ThreadGroup,Runnable,String)} with the exception of the fact - * that it allows the thread stack size to be specified. The stack size - * is the approximate number of bytes of address space that the virtual - * machine is to allocate for this thread's stack. <b>The effect of the - * {@code stackSize} parameter, if any, is highly platform dependent.</b> - * - * <p>On some platforms, specifying a higher value for the - * {@code stackSize} parameter may allow a thread to achieve greater - * recursion depth before throwing a {@link StackOverflowError}. - * Similarly, specifying a lower value may allow a greater number of - * threads to exist concurrently without throwing an {@link - * OutOfMemoryError} (or other internal error). The details of - * the relationship between the value of the <tt>stackSize</tt> parameter - * and the maximum recursion depth and concurrency level are - * platform-dependent. <b>On some platforms, the value of the - * {@code stackSize} parameter may have no effect whatsoever.</b> - * - * <p>The virtual machine is free to treat the {@code stackSize} - * parameter as a suggestion. If the specified value is unreasonably low - * for the platform, the virtual machine may instead use some - * platform-specific minimum value; if the specified value is unreasonably - * high, the virtual machine may instead use some platform-specific - * maximum. Likewise, the virtual machine is free to round the specified - * value up or down as it sees fit (or to ignore it completely). - * - * <p>Specifying a value of zero for the {@code stackSize} parameter will - * cause this constructor to behave exactly like the - * {@code Thread(ThreadGroup, Runnable, String)} constructor. - * - * <p><i>Due to the platform-dependent nature of the behavior of this - * constructor, extreme care should be exercised in its use. - * The thread stack size necessary to perform a given computation will - * likely vary from one JRE implementation to another. In light of this - * variation, careful tuning of the stack size parameter may be required, - * and the tuning may need to be repeated for each JRE implementation on - * which an application is to run.</i> - * - * <p>Implementation note: Java platform implementers are encouraged to - * document their implementation's behavior with respect to the - * {@code stackSize} parameter. - * - * - * @param group - * the thread group. If {@code null} and there is a security - * manager, the group is determined by {@linkplain - * SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. - * If there is not a security manager or {@code - * SecurityManager.getThreadGroup()} returns {@code null}, the group - * is set to the current thread's thread group. - * - * @param target - * the object whose {@code run} method is invoked when this thread - * is started. If {@code null}, this thread's run method is invoked. - * - * @param name - * the name of the new thread - * - * @param stackSize - * the desired stack size for the new thread, or zero to indicate - * that this parameter is to be ignored. - * - * @throws SecurityException - * if the current thread cannot create a thread in the specified - * thread group - * - * @since 1.4 - */ - public Thread(ThreadGroup group, Runnable target, String name, - long stackSize) { - init(group, target, name, stackSize); - } - - /** - * Causes this thread to begin execution; the Java Virtual Machine - * calls the <code>run</code> method of this thread. - * <p> - * The result is that two threads are running concurrently: the - * current thread (which returns from the call to the - * <code>start</code> method) and the other thread (which executes its - * <code>run</code> method). - * <p> - * It is never legal to start a thread more than once. - * In particular, a thread may not be restarted once it has completed - * execution. - * - * @exception IllegalThreadStateException if the thread was already - * started. - * @see #run() - * @see #stop() - */ - public synchronized void start() { - /** - * This method is not invoked for the main method thread or "system" - * group threads created/set up by the VM. Any new functionality added - * to this method in the future may have to also be added to the VM. - * - * A zero status value corresponds to state "NEW". - */ - if (threadStatus != 0) - throw new IllegalThreadStateException(); - - /* Notify the group that this thread is about to be started - * so that it can be added to the group's list of threads - * and the group's unstarted count can be decremented. */ - group.add(this); - - boolean started = false; - try { - start0(); - started = true; - } finally { - try { - if (!started) { - group.threadStartFailed(this); - } - } catch (Throwable ignore) { - /* do nothing. If start0 threw a Throwable then - it will be passed up the call stack */ - } - } - } - - private void start0() { - cli.System.Threading.ThreadStart threadStart = new cli.System.Threading.ThreadStart(new cli.System.Threading.ThreadStart.Method() { - @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation - public void Invoke() { - threadProc(); - } - }); - if (stackSize <= 0) { - nativeThread = new cli.System.Threading.Thread(threadStart); - } - else { - int maxStackSize = (int)Math.min(Math.max(128 * 1024, stackSize), Integer.MAX_VALUE); - nativeThread = new cli.System.Threading.Thread(threadStart, maxStackSize); - } - nativeThread.set_Name(getName()); - nativeThread.set_IsBackground(daemon); - nativeThread.set_Priority(cli.System.Threading.ThreadPriority.wrap(mapJavaPriorityToClr(priority))); - String apartment = Props.props.getProperty("ikvm.apartmentstate", "").toLowerCase(); - if ("mta".equals(apartment)) { - nativeThread.SetApartmentState(cli.System.Threading.ApartmentState.wrap(cli.System.Threading.ApartmentState.MTA)); - } - else if ("sta".equals(apartment)) { - nativeThread.SetApartmentState(cli.System.Threading.ApartmentState.wrap(cli.System.Threading.ApartmentState.STA)); - } - threadStatus = 0x0005; // JVMTI_THREAD_STATE_ALIVE + JVMTI_THREAD_STATE_RUNNABLE - nativeThread.Start(); - if (!daemon) { - cli.System.Threading.Interlocked.Increment(nonDaemonCount); - } - } - - /** - * If this thread was constructed using a separate - * <code>Runnable</code> run object, then that - * <code>Runnable</code> object's <code>run</code> method is called; - * otherwise, this method does nothing and returns. - * <p> - * Subclasses of <code>Thread</code> should override this method. - * - * @see #start() - * @see #stop() - * @see #Thread(ThreadGroup, Runnable, String) - */ - @Override - public void run() { - if (target != null) { - target.run(); - } - } - - // [IKVM] for threads started from Java, this method is called on the thread itself, - // but for .NET threads it will be called by the finalizer of the Cleanup object. - // NOTE there might be a race condition here (when the thread's Cleanup object - // is finalized during AppDomain shutdown while the thread is also exiting on its own), - // but that doesn't matter because Thread.exit() is safe to call multiple times. - void die() { - exit(); - synchronized (lock) { - nativeThread = null; - threadStatus = 0x0002; // JVMTI_THREAD_STATE_TERMINATED - } - wakeupJoinedThreads(); - if (!daemon) { - // TODO there is a race condition in the non-daemon counting - // (setDaemon() isn't synchronized so it may clear/set the daemon flag without the count being affected) - cli.System.Threading.Interlocked.Decrement(nonDaemonCount); - } - if (current == this) { - current = null; - // check if we have a cleanup object, this happens if we attach and subsequently detach from JNI code - if (cleanup != null) { - cli.System.GC.SuppressFinalize(cleanup); - cleanup = null; - } - } - } - - private void wakeupJoinedThreads() { - // HACK locking this here isn't ideal, because we might be invoked from - // the Cleanup object's finalizer and some user code might own the lock and hence - // block the finalizer thread. - // A second scenario is that another thread is currently blocking inside stop() - // (the Thread.Abort() call will block while we are running the finally block) - // and that thread will own the lock on our thread object. - boolean locked = false; - try { - locked = cli.System.Threading.Monitor.TryEnter(this); - if (locked) { - notifyAll(); - } else { - // HACK schedule an asynchronous notification - cli.System.Threading.ThreadPool.QueueUserWorkItem( - new cli.System.Threading.WaitCallback( - new cli.System.Threading.WaitCallback.Method() { - public void Invoke(Object thread) { - synchronized (thread) { - thread.notifyAll(); - } - } - }), this); - } - } - finally { - if (locked) - cli.System.Threading.Monitor.Exit(this); - } - } - - /** - * This method is called by the system to give a Thread - * a chance to clean up before it actually exits. - */ - private void exit() { - if (group != null) { - group.threadTerminated(this); - group = null; - } - /* Aggressively null out all reference fields: see bug 4006245 */ - target = null; - /* Speed the release of some of these resources */ - threadLocals = null; - inheritableThreadLocals = null; - inheritedAccessControlContext = null; - blocker = null; - uncaughtExceptionHandler = null; - } - - /** - * Forces the thread to stop executing. - * <p> - * If there is a security manager installed, its <code>checkAccess</code> - * method is called with <code>this</code> - * as its argument. This may result in a - * <code>SecurityException</code> being raised (in the current thread). - * <p> - * If this thread is different from the current thread (that is, the current - * thread is trying to stop a thread other than itself), the - * security manager's <code>checkPermission</code> method (with a - * <code>RuntimePermission("stopThread")</code> argument) is called in - * addition. - * Again, this may result in throwing a - * <code>SecurityException</code> (in the current thread). - * <p> - * The thread represented by this thread is forced to stop whatever - * it is doing abnormally and to throw a newly created - * <code>ThreadDeath</code> object as an exception. - * <p> - * It is permitted to stop a thread that has not yet been started. - * If the thread is eventually started, it immediately terminates. - * <p> - * An application should not normally try to catch - * <code>ThreadDeath</code> unless it must do some extraordinary - * cleanup operation (note that the throwing of - * <code>ThreadDeath</code> causes <code>finally</code> clauses of - * <code>try</code> statements to be executed before the thread - * officially dies). If a <code>catch</code> clause catches a - * <code>ThreadDeath</code> object, it is important to rethrow the - * object so that the thread actually dies. - * <p> - * The top-level error handler that reacts to otherwise uncaught - * exceptions does not print out a message or otherwise notify the - * application if the uncaught exception is an instance of - * <code>ThreadDeath</code>. - * - * @exception SecurityException if the current thread cannot - * modify this thread. - * @see #interrupt() - * @see #checkAccess() - * @see #run() - * @see #start() - * @see ThreadDeath - * @see ThreadGroup#uncaughtException(Thread,Throwable) - * @see SecurityManager#checkAccess(Thread) - * @see SecurityManager#checkPermission - * @deprecated This method is inherently unsafe. Stopping a thread with - * Thread.stop causes it to unlock all of the monitors that it - * has locked (as a natural consequence of the unchecked - * <code>ThreadDeath</code> exception propagating up the stack). If - * any of the objects previously protected by these monitors were in - * an inconsistent state, the damaged objects become visible to - * other threads, potentially resulting in arbitrary behavior. Many - * uses of <code>stop</code> should be replaced by code that simply - * modifies some variable to indicate that the target thread should - * stop running. The target thread should check this variable - * regularly, and return from its run method in an orderly fashion - * if the variable indicates that it is to stop running. If the - * target thread waits for long periods (on a condition variable, - * for example), the <code>interrupt</code> method should be used to - * interrupt the wait. - * For more information, see - * <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why - * are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. - */ - @Deprecated - public final void stop() { - SecurityManager security = System.getSecurityManager(); - if (security != null) { - checkAccess(); - if (this != Thread.currentThread()) { - security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION); - } - } - // A zero status value corresponds to "NEW", it can't change to - // not-NEW because we hold the lock. - if (threadStatus != 0) { - resume(); // Wake up thread if it was suspended; no-op otherwise - } - - // The VM can handle all thread states - stop0(new ThreadDeath()); - } - - /** - * Throws {@code UnsupportedOperationException}. - * - * @param obj ignored - * - * @deprecated This method was originally designed to force a thread to stop - * and throw a given {@code Throwable} as an exception. It was - * inherently unsafe (see {@link #stop()} for details), and furthermore - * could be used to generate exceptions that the target thread was - * not prepared to handle. - * For more information, see - * <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why - * are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. - */ - @Deprecated - public final synchronized void stop(Throwable obj) { - throw new UnsupportedOperationException(); - } - - /** - * Interrupts this thread. - * - * <p> Unless the current thread is interrupting itself, which is - * always permitted, the {@link #checkAccess() checkAccess} method - * of this thread is invoked, which may cause a {@link - * SecurityException} to be thrown. - * - * <p> If this thread is blocked in an invocation of the {@link - * Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link - * Object#wait(long, int) wait(long, int)} methods of the {@link Object} - * class, or of the {@link #join()}, {@link #join(long)}, {@link - * #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)}, - * methods of this class, then its interrupt status will be cleared and it - * will receive an {@link InterruptedException}. - * - * <p> If this thread is blocked in an I/O operation upon an {@link - * java.nio.channels.InterruptibleChannel InterruptibleChannel} - * then the channel will be closed, the thread's interrupt - * status will be set, and the thread will receive a {@link - * java.nio.channels.ClosedByInterruptException}. - * - * <p> If this thread is blocked in a {@link java.nio.channels.Selector} - * then the thread's interrupt status will be set and it will return - * immediately from the selection operation, possibly with a non-zero - * value, just as if the selector's {@link - * java.nio.channels.Selector#wakeup wakeup} method were invoked. - * - * <p> If none of the previous conditions hold then this thread's interrupt - * status will be set. </p> - * - * <p> Interrupting a thread that is not alive need not have any effect. - * - * @throws SecurityException - * if the current thread cannot modify this thread - * - * @revised 6.0 - * @spec JSR-51 - */ - public void interrupt() { - if (this != Thread.currentThread()) - checkAccess(); - - synchronized (blockerLock) { - Interruptible b = blocker; - if (b != null) { - interrupt0(); // Just to set the interrupt flag - b.interrupt(this); - return; - } - } - interrupt0(); - } - - /** - * Tests whether the current thread has been interrupted. The - * <i>interrupted status</i> of the thread is cleared by this method. In - * other words, if this method were to be called twice in succession, the - * second call would return false (unless the current thread were - * interrupted again, after the first call had cleared its interrupted - * status and before the second call had examined it). - * - * <p>A thread interruption ignored because a thread was not alive - * at the time of the interrupt will be reflected by this method - * returning false. - * - * @return <code>true</code> if the current thread has been interrupted; - * <code>false</code> otherwise. - * @see #isInterrupted() - * @revised 6.0 - */ - public static boolean interrupted() { - Thread current = currentThread(); - if (!current.interruptPending) { - return false; - } - current.interruptPending = false; - return true; - } - - /** - * Tests whether this thread has been interrupted. The <i>interrupted - * status</i> of the thread is unaffected by this method. - * - * <p>A thread interruption ignored because a thread was not alive - * at the time of the interrupt will be reflected by this method - * returning false. - * - * @return <code>true</code> if this thread has been interrupted; - * <code>false</code> otherwise. - * @see #interrupted() - * @revised 6.0 - */ - public boolean isInterrupted() { - return interruptPending; - } - - /** - * Throws {@link NoSuchMethodError}. - * - * @deprecated This method was originally designed to destroy this - * thread without any cleanup. Any monitors it held would have - * remained locked. However, the method was never implemented. - * If if were to be implemented, it would be deadlock-prone in - * much the manner of {@link #suspend}. If the target thread held - * a lock protecting a critical system resource when it was - * destroyed, no thread could ever access this resource again. - * If another thread ever attempted to lock this resource, deadlock - * would result. Such deadlocks typically manifest themselves as - * "frozen" processes. For more information, see - * <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html"> - * Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. - * @throws NoSuchMethodError always - */ - @Deprecated - public void destroy() { - throw new NoSuchMethodError(); - } - - /** - * Tests if this thread is alive. A thread is alive if it has - * been started and has not yet died. - * - * @return <code>true</code> if this thread is alive; - * <code>false</code> otherwise. - */ - public final boolean isAlive() { - return (threadStatus & 0x0001) != 0; - } - - /** - * Suspends this thread. - * <p> - * First, the <code>checkAccess</code> method of this thread is called - * with no arguments. This may result in throwing a - * <code>SecurityException </code>(in the current thread). - * <p> - * If the thread is alive, it is suspended and makes no further - * progress unless and until it is resumed. - * - * @exception SecurityException if the current thread cannot modify - * this thread. - * @see #checkAccess - * @deprecated This method has been deprecated, as it is - * inherently deadlock-prone. If the target thread holds a lock on the - * monitor protecting a critical system resource when it is suspended, no - * thread can access this resource until the target thread is resumed. If - * the thread that would resume the target thread attempts to lock this - * monitor prior to calling <code>resume</code>, deadlock results. Such - * deadlocks typically manifest themselves as "frozen" processes. - * For more information, see - * <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why - * are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. - */ - @Deprecated - public final void suspend() { - checkAccess(); - suspend0(); - } - - /** - * Resumes a suspended thread. - * <p> - * First, the <code>checkAccess</code> method of this thread is called - * with no arguments. This may result in throwing a - * <code>SecurityException</code> (in the current thread). - * <p> - * If the thread is alive but suspended, it is resumed and is - * permitted to make progress in its execution. - * - * @exception SecurityException if the current thread cannot modify this - * thread. - * @see #checkAccess - * @see #suspend() - * @deprecated This method exists solely for use with {@link #suspend}, - * which has been deprecated because it is deadlock-prone. - * For more information, see - * <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why - * are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. - */ - @Deprecated - public final void resume() { - checkAccess(); - resume0(); - } - - /** - * Changes the priority of this thread. - * <p> - * First the <code>checkAccess</code> method of this thread is called - * with no arguments. This may result in throwing a - * <code>SecurityException</code>. - * <p> - * Otherwise, the priority of this thread is set to the smaller of - * the specified <code>newPriority</code> and the maximum permitted - * priority of the thread's thread group. - * - * @param newPriority priority to set this thread to - * @exception IllegalArgumentException If the priority is not in the - * range <code>MIN_PRIORITY</code> to - * <code>MAX_PRIORITY</code>. - * @exception SecurityException if the current thread cannot modify - * this thread. - * @see #getPriority - * @see #checkAccess() - * @see #getThreadGroup() - * @see #MAX_PRIORITY - * @see #MIN_PRIORITY - * @see ThreadGroup#getMaxPriority() - */ - public final void setPriority(int newPriority) { - ThreadGroup g; - checkAccess(); - if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) { - throw new IllegalArgumentException(); - } - if((g = getThreadGroup()) != null) { - if (newPriority > g.getMaxPriority()) { - newPriority = g.getMaxPriority(); - } - setPriority0(priority = newPriority); - } - } - - /** - * Returns this thread's priority. - * - * @return this thread's priority. - * @see #setPriority - */ - public final int getPriority() { - return priority; - } - - /** - * Changes the name of this thread to be equal to the argument - * <code>name</code>. - * <p> - * First the <code>checkAccess</code> method of this thread is called - * with no arguments. This may result in throwing a - * <code>SecurityException</code>. - * - * @param name the new name for this thread. - * @exception SecurityException if the current thread cannot modify this - * thread. - * @see #getName - * @see #checkAccess() - */ - public final synchronized void setName(String name) { - checkAccess(); - this.name = name.toCharArray(); - if (threadStatus != 0) { - setNativeName(name); - } - } - - /** - * Returns this thread's name. - * - * @return this thread's name. - * @see #setName(String) - */ - public final String getName() { - return String.valueOf(name); - } - - /** - * Returns the thread group to which this thread belongs. - * This method returns null if this thread has died - * (been stopped). - * - * @return this thread's thread group. - */ - public final ThreadGroup getThreadGroup() { - return group; - } - - /** - * Returns an estimate of the number of active threads in the current - * thread's {@linkplain java.lang.ThreadGroup thread group} and its - * subgroups. Recursively iterates over all subgroups in the current - * thread's thread group. - * - * <p> The value returned is only an estimate because the number of - * threads may change dynamically while this method traverses internal - * data structures, and might be affected by the presence of certain - * system threads. This method is intended primarily for debugging - * and monitoring purposes. - * - * @return an estimate of the number of active threads in the current - * thread's thread group and in any other thread group that - * has the current thread's thread group as an ancestor - */ - public static int activeCount() { - return currentThread().getThreadGroup().activeCount(); - } - - /** - * Copies into the specified array every active thread in the current - * thread's thread group and its subgroups. This method simply - * invokes the {@link java.lang.ThreadGroup#enumerate(Thread[])} - * method of the current thread's thread group. - * - * <p> An application might use the {@linkplain #activeCount activeCount} - * method to get an estimate of how big the array should be, however - * <i>if the array is too short to hold all the threads, the extra threads - * are silently ignored.</i> If it is critical to obtain every active - * thread in the current thread's thread group and its subgroups, the - * invoker should verify that the returned int value is strictly less - * than the length of {@code tarray}. - * - * <p> Due to the inherent race condition in this method, it is recommended - * that the method only be used for debugging and monitoring purposes. - * - * @param tarray - * an array into which to put the list of threads - * - * @return the number of threads put into the array - * - * @throws SecurityException - * if {@link java.lang.ThreadGroup#checkAccess} determines that - * the current thread cannot access its thread group - */ - public static int enumerate(Thread tarray[]) { - return currentThread().getThreadGroup().enumerate(tarray); - } - - /** - * Counts the number of stack frames in this thread. The thread must - * be suspended. - * - * @return the number of stack frames in this thread. - * @exception IllegalThreadStateException if this thread is not - * suspended. - * @deprecated The definition of this call depends on {@link #suspend}, - * which is deprecated. Further, the results of this call - * were never well-defined. - */ - @Deprecated - public int countStackFrames() { - return 0; - } - - /** - * Waits at most {@code millis} milliseconds for this thread to - * die. A timeout of {@code 0} means to wait forever. - * - * <p> This implementation uses a loop of {@code this.wait} calls - * conditioned on {@code this.isAlive}. As a thread terminates the - * {@code this.notifyAll} method is invoked. It is recommended that - * applications not use {@code wait}, {@code notify}, or - * {@code notifyAll} on {@code Thread} instances. - * - * @param millis - * the time to wait in milliseconds - * - * @throws IllegalArgumentException - * if the value of {@code millis} is negative - * - * @throws InterruptedException - * if any thread has interrupted the current thread. The - * <i>interrupted status</i> of the current thread is - * cleared when this exception is thrown. - */ - public final synchronized void join(long millis) - throws InterruptedException { - long base = System.currentTimeMillis(); - long now = 0; - - if (millis < 0) { - throw new IllegalArgumentException("timeout value is negative"); - } - - if (millis == 0) { - while (isAlive()) { - wait(0); - } - } else { - while (isAlive()) { - long delay = millis - now; - if (delay <= 0) { - break; - } - wait(delay); - now = System.currentTimeMillis() - base; - } - } - } - - /** - * Waits at most {@code millis} milliseconds plus - * {@code nanos} nanoseconds for this thread to die. - * - * <p> This implementation uses a loop of {@code this.wait} calls - * conditioned on {@code this.isAlive}. As a thread terminates the - * {@code this.notifyAll} method is invoked. It is recommended that - * applications not use {@code wait}, {@code notify}, or - * {@code notifyAll} on {@code Thread} instances. - * - * @param millis - * the time to wait in milliseconds - * - * @param nanos - * {@code 0-999999} additional nanoseconds to wait - * - * @throws IllegalArgumentException - * if the value of {@code millis} is negative, or the value - * of {@code nanos} is not in the range {@code 0-999999} - * - * @throws InterruptedException - * if any thread has interrupted the current thread. The - * <i>interrupted status</i> of the current thread is - * cleared when this exception is thrown. - */ - public final synchronized void join(long millis, int nanos) - throws InterruptedException { - - if (millis < 0) { - throw new IllegalArgumentException("timeout value is negative"); - } - - if (nanos < 0 || nanos > 999999) { - throw new IllegalArgumentException( - "nanosecond timeout value out of range"); - } - - if (nanos >= 500000 || (nanos != 0 && millis == 0)) { - millis++; - } - - join(millis); - } - - /** - * Waits for this thread to die. - * - * <p> An invocation of this method behaves in exactly the same - * way as the invocation - * - * <blockquote> - * {@linkplain #join(long) join}{@code (0)} - * </blockquote> - * - * @throws InterruptedException - * if any thread has interrupted the current thread. The - * <i>interrupted status</i> of the current thread is - * cleared when this exception is thrown. - */ - public final void join() throws InterruptedException { - join(0); - } - - /** - * Prints a stack trace of the current thread to the standard error stream. - * This method is used only for debugging. - * - * @see Throwable#printStackTrace() - */ - public static void dumpStack() { - new Exception("Stack trace").printStackTrace(); - } - - /** - * Marks this thread as either a {@linkplain #isDaemon daemon} thread - * or a user thread. The Java Virtual Machine exits when the only - * threads running are all daemon threads. - * - * <p> This method must be invoked before the thread is started. - * - * @param on - * if {@code true}, marks this thread as a daemon thread - * - * @throws IllegalThreadStateException - * if this thread is {@linkplain #isAlive alive} - * - * @throws SecurityException - * if {@link #checkAccess} determines that the current - * thread cannot modify this thread - */ - public final void setDaemon(boolean on) { - checkAccess(); - if (isAlive()) { - throw new IllegalThreadStateException(); - } - daemon = on; - } - - /** - * Tests if this thread is a daemon thread. - * - * @return <code>true</code> if this thread is a daemon thread; - * <code>false</code> otherwise. - * @see #setDaemon(boolean) - */ - public final boolean isDaemon() { - return daemon; - } - - /** - * Determines if the currently running thread has permission to - * modify this thread. - * <p> - * If there is a security manager, its <code>checkAccess</code> method - * is called with this thread as its argument. This may result in - * throwing a <code>SecurityException</code>. - * - * @exception SecurityException if the current thread is not allowed to - * access this thread. - * @see SecurityManager#checkAccess(Thread) - */ - public final void checkAccess() { - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkAccess(this); - } - } - - /** - * Returns a string representation of this thread, including the - * thread's name, priority, and thread group. - * - * @return a string representation of this thread. - */ - public String toString() { - ThreadGroup group = getThreadGroup(); - if (group != null) { - return "Thread[" + getName() + "," + getPriority() + "," + - group.getName() + "]"; - } else { - return "Thread[" + getName() + "," + getPriority() + "," + - "" + "]"; - } - } - - /** - * Returns the context ClassLoader for this Thread. The context - * ClassLoader is provided by the creator of the thread for use - * by code running in this thread when loading classes and resources. - * If not {@linkplain #setContextClassLoader set}, the default is the - * ClassLoader context of the parent Thread. The context ClassLoader of the - * primordial thread is typically set to the class loader used to load the - * application. - * - * <p>If a security manager is present, and the invoker's class loader is not - * {@code null} and is not the same as or an ancestor of the context class - * loader, then this method invokes the security manager's {@link - * SecurityManager#checkPermission(java.security.Permission) checkPermission} - * method with a {@link RuntimePermission RuntimePermission}{@code - * ("getClassLoader")} permission to verify that retrieval of the context - * class loader is permitted. - * - * @return the context ClassLoader for this Thread, or {@code null} - * indicating the system class loader (or, failing that, the - * bootstrap class loader) - * - * @throws SecurityException - * if the current thread cannot get the context ClassLoader - * - * @since 1.2 - */ - @CallerSensitive - public ClassLoader getContextClassLoader() { - if (contextClassLoader == ClassLoader.DUMMY) { - contextClassLoader = ClassLoader.getSystemClassLoader(); - } - if (contextClassLoader == null) - return null; - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - ClassLoader.checkClassLoaderPermission(contextClassLoader, - Reflection.getCallerClass()); - } - return contextClassLoader; - } - - /** - * Sets the context ClassLoader for this Thread. The context - * ClassLoader can be set when a thread is created, and allows - * the creator of the thread to provide the appropriate class loader, - * through {@code getContextClassLoader}, to code running in the thread - * when loading classes and resources. - * - * <p>If a security manager is present, its {@link - * SecurityManager#checkPermission(java.security.Permission) checkPermission} - * method is invoked with a {@link RuntimePermission RuntimePermission}{@code - * ("setContextClassLoader")} permission to see if setting the context - * ClassLoader is permitted. - * - * @param cl - * the context ClassLoader for this Thread, or null indicating the - * system class loader (or, failing that, the bootstrap class loader) - * - * @throws SecurityException - * if the current thread cannot set the context ClassLoader - * - * @since 1.2 - */ - public void setContextClassLoader(ClassLoader cl) { - if (cl == ClassLoader.DUMMY) { - // we're being called by Thread.<clinit> to force this method to be JIT compiled - return; - } - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("setContextClassLoader")); - } - contextClassLoader = cl; - } - - // [IKVM] called by sun.misc.Launcher (via map.xml patch) to initialize the context class loader - final void initContextClassLoader(ClassLoader cl) { - // we only set contextClassLoader if it hasn't been set (by user code) previously - java.util.concurrent.atomic.AtomicReferenceFieldUpdater - .newUpdater(Thread.class, ClassLoader.class, "contextClassLoader") - .compareAndSet(this, ClassLoader.DUMMY, cl); - } - - /** - * Returns <tt>true</tt> if and only if the current thread holds the - * monitor lock on the specified object. - * - * <p>This method is designed to allow a program to assert that - * the current thread already holds a specified lock: - * <pre> - * assert Thread.holdsLock(obj); - * </pre> - * - * @param obj the object on which to test lock ownership - * @throws NullPointerException if obj is <tt>null</tt> - * @return <tt>true</tt> if the current thread holds the monitor lock on - * the specified object. - * @since 1.4 - */ - public static boolean holdsLock(Object obj) { - if (obj == null) { - throw new NullPointerException(); - } - try { - if (false) throw new cli.System.Threading.SynchronizationLockException(); - // The 1.5 memory model (JSR133) explicitly allows spurious wake-ups from Object.wait, - // so we abuse Pulse to check if we own the monitor. - cli.System.Threading.Monitor.Pulse(obj); - return true; - } - catch (cli.System.Threading.SynchronizationLockException _) { - return false; - } - } - - private static final StackTraceElement[] EMPTY_STACK_TRACE - = new StackTraceElement[0]; - - /** - * Returns an array of stack trace elements representing the stack dump - * of this thread. This method will return a zero-length array if - * this thread has not started, has started but has not yet been - * scheduled to run by the system, or has terminated. - * If the returned array is of non-zero length then the first element of - * the array represents the top of the stack, which is the most recent - * method invocation in the sequence. The last element of the array - * represents the bottom of the stack, which is the least recent method - * invocation in the sequence. - * - * <p>If there is a security manager, and this thread is not - * the current thread, then the security manager's - * <tt>checkPermission</tt> method is called with a - * <tt>RuntimePermission("getStackTrace")</tt> permission - * to see if it's ok to get the stack trace. - * - * <p>Some virtual machines may, under some circumstances, omit one - * or more stack frames from the stack trace. In the extreme case, - * a virtual machine that has no stack trace information concerning - * this thread is permitted to return a zero-length array from this - * method. - * - * @return an array of <tt>StackTraceElement</tt>, - * each represents one stack frame. - * - * @throws SecurityException - * if a security manager exists and its - * <tt>checkPermission</tt> method doesn't allow - * getting the stack trace of thread. - * @see SecurityManager#checkPermission - * @see RuntimePermission - * @see Throwable#getStackTrace - * - * @since 1.5 - */ - public StackTraceElement[] getStackTrace() { - if (this != Thread.currentThread()) { - // check for getStackTrace permission - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkPermission( - SecurityConstants.GET_STACK_TRACE_PERMISSION); - } - // optimization so we do not call into the vm for threads that - // have not yet started or have terminated - if (!isAlive()) { - return EMPTY_STACK_TRACE; - } - StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this}); - StackTraceElement[] stackTrace = stackTraceArray[0]; - // a thread that was alive during the previous isAlive call may have - // since terminated, therefore not having a stacktrace. - if (stackTrace == null) { - stackTrace = EMPTY_STACK_TRACE; - } - return stackTrace; - } else { - // Don't need JVM help for current thread - return (new Exception()).getStackTrace(); - } - } - - /** - * Returns a map of stack traces for all live threads. - * The map keys are threads and each map value is an array of - * <tt>StackTraceElement</tt> that represents the stack dump - * of the corresponding <tt>Thread</tt>. - * The returned stack traces are in the format specified for - * the {@link #getStackTrace getStackTrace} method. - * - * <p>The threads may be executing while this method is called. - * The stack trace of each thread only represents a snapshot and - * each stack trace may be obtained at different time. A zero-length - * array will be returned in the map value if the virtual machine has - * no stack trace information about a thread. - * - * <p>If there is a security manager, then the security manager's - * <tt>checkPermission</tt> method is called with a - * <tt>RuntimePermission("getStackTrace")</tt> permission as well as - * <tt>RuntimePermission("modifyThreadGroup")</tt> permission - * to see if it is ok to get the stack trace of all threads. - * - * @return a <tt>Map</tt> from <tt>Thread</tt> to an array of - * <tt>StackTraceElement</tt> that represents the stack trace of - * the corresponding thread. - * - * @throws SecurityException - * if a security manager exists and its - * <tt>checkPermission</tt> method doesn't allow - * getting the stack trace of thread. - * @see #getStackTrace - * @see SecurityManager#checkPermission - * @see RuntimePermission - * @see Throwable#getStackTrace - * - * @since 1.5 - */ - public static Map<Thread, StackTraceElement[]> getAllStackTraces() { - // check for getStackTrace permission - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkPermission( - SecurityConstants.GET_STACK_TRACE_PERMISSION); - security.checkPermission( - SecurityConstants.MODIFY_THREADGROUP_PERMISSION); - } - - // Get a snapshot of the list of all threads - Thread[] threads = getThreads(); - StackTraceElement[][] traces = dumpThreads(threads); - Map<Thread, StackTraceElement[]> m = new HashMap<>(threads.length); - for (int i = 0; i < threads.length; i++) { - StackTraceElement[] stackTrace = traces[i]; - if (stackTrace != null) { - m.put(threads[i], stackTrace); - } - // else terminated so we don't put it in the map - } - return m; - } - - - private static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION = - new RuntimePermission("enableContextClassLoaderOverride"); - - /** cache of subclass security audit results */ - /* Replace with ConcurrentReferenceHashMap when/if it appears in a future - * release */ - private static class Caches { - /** cache of subclass security audit results */ - static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits = - new ConcurrentHashMap<>(); - - /** queue for WeakReferences to audited subclasses */ - static final ReferenceQueue<Class<?>> subclassAuditsQueue = - new ReferenceQueue<>(); - } - - /** - * Verifies that this (possibly subclass) instance can be constructed - * without violating security constraints: the subclass must not override - * security-sensitive non-final methods, or else the - * "enableContextClassLoaderOverride" RuntimePermission is checked. - */ - @cli.System.Runtime.CompilerServices.MethodImplAttribute.Annotation(value = cli.System.Runtime.CompilerServices.MethodImplOptions.__Enum.NoInlining) - private static native boolean isCCLOverridden(Thread thread); // [IKVM] implemented in map.xml - - private static boolean isCCLOverridden(Class<?> cl) { - if (cl == Thread.class) - return false; - - processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits); - WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue); - Boolean result = Caches.subclassAudits.get(key); - if (result == null) { - result = Boolean.valueOf(auditSubclass(cl)); - Caches.subclassAudits.putIfAbsent(key, result); - } - - return result.booleanValue(); - } - - /** - * Performs reflective checks on given subclass to verify that it doesn't - * override security-sensitive non-final methods. Returns true if the - * subclass overrides any of the methods, false otherwise. - */ - private static boolean auditSubclass(final Class<?> subcl) { - Boolean result = AccessController.doPrivileged( - new PrivilegedAction<Boolean>() { - public Boolean run() { - for (Class<?> cl = subcl; - cl != Thread.class; - cl = cl.getSuperclass()) - { - try { - cl.getDeclaredMethod("getContextClassLoader", new Class<?>[0]); - return Boolean.TRUE; - } catch (NoSuchMethodException ex) { - } - try { - Class<?>[] params = {ClassLoader.class}; - cl.getDeclaredMethod("setContextClassLoader", params); - return Boolean.TRUE; - } catch (NoSuchMethodException ex) { - } - } - return Boolean.FALSE; - } - } - ); - return result.booleanValue(); - } - - private static StackTraceElement[][] dumpThreads(Thread[] threads) { - StackTraceElement[][] stacks = new StackTraceElement[threads.length][]; - for (int i = 0; i < threads.length; i++) { - cli.System.Threading.Thread nativeThread = threads[i].nativeThread; - if (nativeThread == null) { - stacks[i] = new StackTraceElement[0]; - } else { - try { - if (false) throw new cli.System.Threading.ThreadStateException(); - boolean suspended = false; - if ((nativeThread.get_ThreadState().Value & cli.System.Threading.ThreadState.Suspended) == 0 && nativeThread != cli.System.Threading.Thread.get_CurrentThread()) { - suspended = true; - nativeThread.Suspend(); - } - cli.System.Diagnostics.StackTrace stack; - try { - stack = new cli.System.Diagnostics.StackTrace(nativeThread, true); - } - finally { - if (suspended) { - nativeThread.Resume(); - } - } - stacks[i] = getStackTrace(stack); - } - catch (cli.System.Threading.ThreadStateException _) { - stacks[i] = new StackTraceElement[0]; - } - } - } - return stacks; - } - - private static native StackTraceElement[] getStackTrace(cli.System.Diagnostics.StackTrace stack); - - private static native Thread[] getThreads(); - - /** - * Returns the identifier of this Thread. The thread ID is a positive - * <tt>long</tt> number generated when this thread was created. - * The thread ID is unique and remains unchanged during its lifetime. - * When a thread is terminated, this thread ID may be reused. - * - * @return this thread's ID. - * @since 1.5 - */ - public long getId() { - return tid; - } - - /** - * A thread state. A thread can be in one of the following states: - * <ul> - * <li>{@link #NEW}<br> - * A thread that has not yet started is in this state. - * </li> - * <li>{@link #RUNNABLE}<br> - * A thread executing in the Java virtual machine is in this state. - * </li> - * <li>{@link #BLOCKED}<br> - * A thread that is blocked waiting for a monitor lock - * is in this state. - * </li> - * <li>{@link #WAITING}<br> - * A thread that is waiting indefinitely for another thread to - * perform a particular action is in this state. - * </li> - * <li>{@link #TIMED_WAITING}<br> - * A thread that is waiting for another thread to perform an action - * for up to a specified waiting time is in this state. - * </li> - * <li>{@link #TERMINATED}<br> - * A thread that has exited is in this state. - * </li> - * </ul> - * - * <p> - * A thread can be in only one state at a given point in time. - * These states are virtual machine states which do not reflect - * any operating system thread states. - * - * @since 1.5 - * @see #getState - */ - public enum State { - /** - * Thread state for a thread which has not yet started. - */ - NEW, - - /** - * Thread state for a runnable thread. A thread in the runnable - * state is executing in the Java virtual machine but it may - * be waiting for other resources from the operating system - * such as processor. - */ - RUNNABLE, - - /** - * Thread state for a thread blocked waiting for a monitor lock. - * A thread in the blocked state is waiting for a monitor lock - * to enter a synchronized block/method or - * reenter a synchronized block/method after calling - * {@link Object#wait() Object.wait}. - */ - BLOCKED, - - /** - * Thread state for a waiting thread. - * A thread is in the waiting state due to calling one of the - * following methods: - * <ul> - * <li>{@link Object#wait() Object.wait} with no timeout</li> - * <li>{@link #join() Thread.join} with no timeout</li> - * <li>{@link LockSupport#park() LockSupport.park}</li> - * </ul> - * - * <p>A thread in the waiting state is waiting for another thread to - * perform a particular action. - * - * For example, a thread that has called <tt>Object.wait()</tt> - * on an object is waiting for another thread to call - * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on - * that object. A thread that has called <tt>Thread.join()</tt> - * is waiting for a specified thread to terminate. - */ - WAITING, - - /** - * Thread state for a waiting thread with a specified waiting time. - * A thread is in the timed waiting state due to calling one of - * the following methods with a specified positive waiting time: - * <ul> - * <li>{@link #sleep Thread.sleep}</li> - * <li>{@link Object#wait(long) Object.wait} with timeout</li> - * <li>{@link #join(long) Thread.join} with timeout</li> - * <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li> - * <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li> - * </ul> - */ - TIMED_WAITING, - - /** - * Thread state for a terminated thread. - * The thread has completed execution. - */ - TERMINATED; - } - - /** - * Returns the state of this thread. - * This method is designed for use in monitoring of the system state, - * not for synchronization control. - * - * @return this thread's state. - * @since 1.5 - */ - public State getState() { - // get current thread state - switch (threadStatus) { - case 0: - return State.NEW; - case 0x0002: - return State.TERMINATED; - } - synchronized (lock) { - if (interruptableWait) { - // NOTE if objectWait has satisfied the wait condition (or has been interrupted or has timed-out), - // it can be blocking on the re-acquire of the monitor, but we have no way of detecting that. - return timedWait ? State.TIMED_WAITING : State.WAITING; - } - } - cli.System.Threading.Thread nativeThread = this.nativeThread; - if (nativeThread == null) { - return State.TERMINATED; - } - if ((nativeThread.get_ThreadState().Value & cli.System.Threading.ThreadState.WaitSleepJoin) != 0) { - return State.BLOCKED; - } - return State.RUNNABLE; - } - - // Added in JSR-166 - - /** - * Interface for handlers invoked when a <tt>Thread</tt> abruptly - * terminates due to an uncaught exception. - * <p>When a thread is about to terminate due to an uncaught exception - * the Java Virtual Machine will query the thread for its - * <tt>UncaughtExceptionHandler</tt> using - * {@link #getUncaughtExceptionHandler} and will invoke the handler's - * <tt>uncaughtException</tt> method, passing the thread and the - * exception as arguments. - * If a thread has not had its <tt>UncaughtExceptionHandler</tt> - * explicitly set, then its <tt>ThreadGroup</tt> object acts as its - * <tt>UncaughtExceptionHandler</tt>. If the <tt>ThreadGroup</tt> object - * has no - * special requirements for dealing with the exception, it can forward - * the invocation to the {@linkplain #getDefaultUncaughtExceptionHandler - * default uncaught exception handler}. - * - * @see #setDefaultUncaughtExceptionHandler - * @see #setUncaughtExceptionHandler - * @see ThreadGroup#uncaughtException - * @since 1.5 - */ - @FunctionalInterface - public interface UncaughtExceptionHandler { - /** - * Method invoked when the given thread terminates due to the - * given uncaught exception. - * <p>Any exception thrown by this method will be ignored by the - * Java Virtual Machine. - * @param t the thread - * @param e the exception - */ - void uncaughtException(Thread t, Throwable e); - } - - // null unless explicitly set - private volatile UncaughtExceptionHandler uncaughtExceptionHandler; - - // null unless explicitly set - private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler; - - /** - * Set the default handler invoked when a thread abruptly terminates - * due to an uncaught exception, and no other handler has been defined - * for that thread. - * - * <p>Uncaught exception handling is controlled first by the thread, then - * by the thread's {@link ThreadGroup} object and finally by the default - * uncaught exception handler. If the thread does not have an explicit - * uncaught exception handler set, and the thread's thread group - * (including parent thread groups) does not specialize its - * <tt>uncaughtException</tt> method, then the default handler's - * <tt>uncaughtException</tt> method will be invoked. - * <p>By setting the default uncaught exception handler, an application - * can change the way in which uncaught exceptions are handled (such as - * logging to a specific device, or file) for those threads that would - * already accept whatever "default" behavior the system - * provided. - * - * <p>Note that the default uncaught exception handler should not usually - * defer to the thread's <tt>ThreadGroup</tt> object, as that could cause - * infinite recursion. - * - * @param eh the object to use as the default uncaught exception handler. - * If <tt>null</tt> then there is no default handler. - * - * @throws SecurityException if a security manager is present and it - * denies <tt>{@link RuntimePermission} - * ("setDefaultUncaughtExceptionHandler")</tt> - * - * @see #setUncaughtExceptionHandler - * @see #getUncaughtExceptionHandler - * @see ThreadGroup#uncaughtException - * @since 1.5 - */ - public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission( - new RuntimePermission("setDefaultUncaughtExceptionHandler") - ); - } - - defaultUncaughtExceptionHandler = eh; - } - - /** - * Returns the default handler invoked when a thread abruptly terminates - * due to an uncaught exception. If the returned value is <tt>null</tt>, - * there is no default. - * @since 1.5 - * @see #setDefaultUncaughtExceptionHandler - * @return the default uncaught exception handler for all threads - */ - public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){ - return defaultUncaughtExceptionHandler; - } - - /** - * Returns the handler invoked when this thread abruptly terminates - * due to an uncaught exception. If this thread has not had an - * uncaught exception handler explicitly set then this thread's - * <tt>ThreadGroup</tt> object is returned, unless this thread - * has terminated, in which case <tt>null</tt> is returned. - * @since 1.5 - * @return the uncaught exception handler for this thread - */ - public UncaughtExceptionHandler getUncaughtExceptionHandler() { - return uncaughtExceptionHandler != null ? - uncaughtExceptionHandler : group; - } - - /** - * Set the handler invoked when this thread abruptly terminates - * due to an uncaught exception. - * <p>A thread can take full control of how it responds to uncaught - * exceptions by having its uncaught exception handler explicitly set. - * If no such handler is set then the thread's <tt>ThreadGroup</tt> - * object acts as its handler. - * @param eh the object to use as this thread's uncaught exception - * handler. If <tt>null</tt> then this thread has no explicit handler. - * @throws SecurityException if the current thread is not allowed to - * modify this thread. - * @see #setDefaultUncaughtExceptionHandler - * @see ThreadGroup#uncaughtException - * @since 1.5 - */ - public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) { - checkAccess(); - uncaughtExceptionHandler = eh; - } - - /** - * Dispatch an uncaught exception to the handler. This method is - * intended to be called only by the JVM. - */ - private void dispatchUncaughtException(Throwable e) { - getUncaughtExceptionHandler().uncaughtException(this, e); - } - - /** - * Removes from the specified map any keys that have been enqueued - * on the specified reference queue. - */ - static void processQueue(ReferenceQueue<Class<?>> queue, - ConcurrentMap<? extends - WeakReference<Class<?>>, ?> map) - { - Reference<? extends Class<?>> ref; - while((ref = queue.poll()) != null) { - map.remove(ref); - } - } - - /** - * Weak key for Class objects. - **/ - static class WeakClassKey extends WeakReference<Class<?>> { - /** - * saved value of the referent's identity hash code, to maintain - * a consistent hash code after the referent has been cleared - */ - private final int hash; - - /** - * Create a new WeakClassKey to the given object, registered - * with a queue. - */ - WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) { - super(cl, refQueue); - hash = System.identityHashCode(cl); - } - - /** - * Returns the identity hash code of the original referent. - */ - @Override - public int hashCode() { - return hash; - } - - /** - * Returns true if the given object is this identical - * WeakClassKey instance, or, if this object's referent has not - * been cleared, if the given object is another WeakClassKey - * instance with the identical non-null referent as this one. - */ - @Override - public boolean equals(Object obj) { - if (obj == this) - return true; - - if (obj instanceof WeakClassKey) { - Object referent = get(); - return (referent != null) && - (referent == ((WeakClassKey) obj).get()); - } else { - return false; - } - } - } - - - // The following three initially uninitialized fields are exclusively - // managed by class java.util.concurrent.ThreadLocalRandom. These - // fields are used to build the high-performance PRNGs in the - // concurrent code, and we can not risk accidental false sharing. - // Hence, the fields are isolated with @Contended. - - /** The current seed for a ThreadLocalRandom */ - @sun.misc.Contended("tlr") - long threadLocalRandomSeed; - - /** Probe hash value; nonzero if threadLocalRandomSeed initialized */ - @sun.misc.Contended("tlr") - @ikvm.lang.Internal // [IKVM] accessed from java.util.concurrent.atomic.Striped64 - public int threadLocalRandomProbe; - - /** Secondary seed isolated from public ThreadLocalRandom sequence */ - @sun.misc.Contended("tlr") - @ikvm.lang.Internal // [IKVM] accessed from java.util.concurrent.locks.LockSupport - public int threadLocalRandomSecondarySeed; - - /* Some private helper methods */ - private synchronized void setPriority0(int newPriority) { - cli.System.Threading.Thread nativeThread = this.nativeThread; - if (nativeThread != null) { - try { - if (false) throw new cli.System.Threading.ThreadStateException(); - nativeThread.set_Priority(cli.System.Threading.ThreadPriority.wrap(mapJavaPriorityToClr(newPriority))); - } - catch (cli.System.Threading.ThreadStateException _) { - } - } - } - - private void stop0(Throwable x) { - synchronized (lock) { - if (!running) { - stillborn = x; - x = null; - } - } - if (x != null) { - // NOTE we allow ThreadDeath (and its subclasses) to be thrown on every thread, but any - // other exception is ignored, except if we're throwing it on the current Thread. This - // is done to allow exception handlers to be type specific, otherwise every exception - // handler would have to catch ThreadAbortException and look inside it to see if it - // contains the real exception that we wish to handle. - // I hope we can get away with this behavior, because Thread.stop() is deprecated - // anyway. Note that we do allow arbitrary exceptions to be thrown on the current - // thread, since this is harmless (because they aren't wrapped) and also because it - // provides some real value, because it is one of the ways you can throw arbitrary checked - // exceptions from Java. - if (this == current) { - sun.misc.Unsafe.getUnsafe().throwException(x); - } - else if (x instanceof ThreadDeath) { - cli.System.Threading.Thread nativeThread = this.nativeThread; - if (nativeThread == null) { - return; - } - try { - if (false) throw new cli.System.Threading.ThreadStateException(); - nativeThread.Abort(x); - } - catch (cli.System.Threading.ThreadStateException _) { - // .NET 2.0 throws a ThreadStateException if the target thread is currently suspended - // (but it does record the Abort request) - } - try { - if (false) throw new cli.System.Threading.ThreadStateException(); - int suspend = cli.System.Threading.ThreadState.Suspended | cli.System.Threading.ThreadState.SuspendRequested; - while ((nativeThread.get_ThreadState().Value & suspend) != 0) { - nativeThread.Resume(); - } - } - catch (cli.System.Threading.ThreadStateException _) { - } - } - } - } - - private void suspend0() { - try { - if (false) throw new cli.System.Threading.ThreadStateException(); - cli.System.Threading.Thread nativeThread = this.nativeThread; - if (nativeThread != null) { - nativeThread.Suspend(); - } - } - catch (cli.System.Threading.ThreadStateException _) { - } - } - - private void resume0() { - try { - if (false) throw new cli.System.Threading.ThreadStateException(); - cli.System.Threading.Thread nativeThread = this.nativeThread; - if (nativeThread != null) { - nativeThread.Resume(); - } - } - catch (cli.System.Threading.ThreadStateException _) { - } - } - - private void interrupt0() { - synchronized (lock) { - // if the thread hasn't been started yet or has been terminated, the interrupt is ignored - // (like on the reference implementation) - if (nativeThread == null) { - return; - } - if (!interruptPending) { - interruptPending = true; - if (interruptableWait) { - nativeInterruptPending = true; - nativeThread.Interrupt(); - } - } - } - } - - private void setRunningAndCheckStillborn() throws Throwable { - Throwable x; - synchronized (lock) { - running = true; - x = stillborn; - stillborn = null; - } - if (x != null) { - throw x; - } - } - - // [IKVM] this the entry point of thread started from Java - @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation - void threadProc() { - current = this; - try { - // the body of the try block is in another method to allow the (limited) try/finally optimizer - // to properly recognize the try/finally block, because we want to make sure that die() - // runs in a finally block to prevent it from being asynchronously aborted. - threadProc2(); - } - finally { - die(); - } - } - - @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation - private void threadProc2() { - try { - setRunningAndCheckStillborn(); - run(); - } - catch (Throwable x) { - try { - getUncaughtExceptionHandler().uncaughtException(this, x); - } - catch (Throwable _) { - } - } - } - - // [IKVM] this the implementation of Object.wait(long timeout, int nanos). It is hooked up in map.xml. - static void objectWait(Object o, long timeout, int nanos) throws InterruptedException { - if (o == null) { - throw new NullPointerException(); - } - if (timeout < 0) { - throw new IllegalArgumentException("timeout value is negative"); - } - if (nanos < 0 || nanos > 999999) { - throw new IllegalArgumentException("nanosecond timeout value out of range"); - } - if (nanos >= 500000 || (nanos != 0 && timeout == 0)) { - timeout++; - } - objectWait(o, timeout); - } - - // [IKVM] this the implementation of Object.wait(long timeout). It is hooked up in map.xml. - static void objectWait(Object o, long timeout) throws InterruptedException { - if (o == null) { - throw new NullPointerException(); - } - if (timeout < 0) { - throw new IllegalArgumentException("timeout value is negative"); - } - Thread t = currentThread(); - t.enterInterruptableWait(timeout != 0); - try { - if (false) throw new cli.System.Threading.ThreadInterruptedException(); - if (timeout == 0 || timeout > 922337203685476L) { - cli.System.Threading.Monitor.Wait(o); - } - else { - // We wait a maximum of Integer.MAX_VALUE milliseconds, because that is the maximum that Monitor.Wait will wait. - // Note that the Object.wait() specification allows for spurious wakeups, so this isn't a problem. Trying to - // emulate a longer wait with multiple Monitor.Wait() calls is not allowed, because that would mean that - // we acquire and release the synchronization lock multiple times during the wait. - cli.System.Threading.Monitor.Wait(o, (int)Math.min(timeout, Integer.MAX_VALUE)); - } - } - catch (cli.System.Threading.ThreadInterruptedException _) { - } - finally { - t.leaveInterruptableWait(); - } - } - - private void setNativeName(String name) { - cli.System.Threading.Thread thread = nativeThread; - if (thread != null) { - try { - if (false) throw new cli.System.InvalidOperationException(); - thread.set_Name(name); - } catch (cli.System.InvalidOperationException _) { - } - } - } -} diff --git a/openjdk/java/lang/ThrowableHelper.java b/openjdk/java/lang/ThrowableHelper.java deleted file mode 100644 index 8a08a8fe..00000000 --- a/openjdk/java/lang/ThrowableHelper.java +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright (c) 1994, 2011, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang; -import java.io.*; -import java.util.*; - -final class ThrowableHelper { - /** - * Holder class to defer initializing sentinel objects only used - * for serialization. - */ - private static class SentinelHolder { - /** - * {@linkplain #setStackTrace(StackTraceElement[]) Setting the - * stack trace} to a one-element array containing this sentinel - * value indicates future attempts to set the stack trace will be - * ignored. The sentinal is equal to the result of calling:<br> - * {@code new StackTraceElement("", "", null, Integer.MIN_VALUE)} - */ - public static final StackTraceElement STACK_TRACE_ELEMENT_SENTINEL = - new StackTraceElement("", "", null, Integer.MIN_VALUE); - - /** - * Sentinel value used in the serial form to indicate an immutable - * stack trace. - */ - public static final StackTraceElement[] STACK_TRACE_SENTINEL = - new StackTraceElement[] {STACK_TRACE_ELEMENT_SENTINEL}; - } - - /** Caption for labeling causative exception stack traces */ - private static final String CAUSE_CAPTION = "Caused by: "; - - /** Caption for labeling suppressed exception stack traces */ - private static final String SUPPRESSED_CAPTION = "Suppressed: "; - - /** - * Prints this throwable and its backtrace to the - * standard error stream. This method prints a stack trace for this - * {@code Throwable} object on the error output stream that is - * the value of the field {@code System.err}. The first line of - * output contains the result of the {@link #toString()} method for - * this object. Remaining lines represent data previously recorded by - * the method {@link #fillInStackTrace()}. The format of this - * information depends on the implementation, but the following - * example may be regarded as typical: - * <blockquote><pre> - * java.lang.NullPointerException - * at MyClass.mash(MyClass.java:9) - * at MyClass.crunch(MyClass.java:6) - * at MyClass.main(MyClass.java:3) - * </pre></blockquote> - * This example was produced by running the program: - * <pre> - * class MyClass { - * public static void main(String[] args) { - * crunch(null); - * } - * static void crunch(int[] a) { - * mash(a); - * } - * static void mash(int[] b) { - * System.out.println(b[0]); - * } - * } - * </pre> - * The backtrace for a throwable with an initialized, non-null cause - * should generally include the backtrace for the cause. The format - * of this information depends on the implementation, but the following - * example may be regarded as typical: - * <pre> - * HighLevelException: MidLevelException: LowLevelException - * at Junk.a(Junk.java:13) - * at Junk.main(Junk.java:4) - * Caused by: MidLevelException: LowLevelException - * at Junk.c(Junk.java:23) - * at Junk.b(Junk.java:17) - * at Junk.a(Junk.java:11) - * ... 1 more - * Caused by: LowLevelException - * at Junk.e(Junk.java:30) - * at Junk.d(Junk.java:27) - * at Junk.c(Junk.java:21) - * ... 3 more - * </pre> - * Note the presence of lines containing the characters {@code "..."}. - * These lines indicate that the remainder of the stack trace for this - * exception matches the indicated number of frames from the bottom of the - * stack trace of the exception that was caused by this exception (the - * "enclosing" exception). This shorthand can greatly reduce the length - * of the output in the common case where a wrapped exception is thrown - * from same method as the "causative exception" is caught. The above - * example was produced by running the program: - * <pre> - * public class Junk { - * public static void main(String args[]) { - * try { - * a(); - * } catch(HighLevelException e) { - * e.printStackTrace(); - * } - * } - * static void a() throws HighLevelException { - * try { - * b(); - * } catch(MidLevelException e) { - * throw new HighLevelException(e); - * } - * } - * static void b() throws MidLevelException { - * c(); - * } - * static void c() throws MidLevelException { - * try { - * d(); - * } catch(LowLevelException e) { - * throw new MidLevelException(e); - * } - * } - * static void d() throws LowLevelException { - * e(); - * } - * static void e() throws LowLevelException { - * throw new LowLevelException(); - * } - * } - * - * class HighLevelException extends Exception { - * HighLevelException(Throwable cause) { super(cause); } - * } - * - * class MidLevelException extends Exception { - * MidLevelException(Throwable cause) { super(cause); } - * } - * - * class LowLevelException extends Exception { - * } - * </pre> - * As of release 7, the platform supports the notion of - * <i>suppressed exceptions</i> (in conjunction with the {@code - * try}-with-resources statement). Any exceptions that were - * suppressed in order to deliver an exception are printed out - * beneath the stack trace. The format of this information - * depends on the implementation, but the following example may be - * regarded as typical: - * - * <pre> - * Exception in thread "main" java.lang.Exception: Something happened - * at Foo.bar(Foo.java:10) - * at Foo.main(Foo.java:5) - * Suppressed: Resource$CloseFailException: Resource ID = 0 - * at Resource.close(Resource.java:26) - * at Foo.bar(Foo.java:9) - * ... 1 more - * </pre> - * Note that the "... n more" notation is used on suppressed exceptions - * just at it is used on causes. Unlike causes, suppressed exceptions are - * indented beyond their "containing exceptions." - * - * <p>An exception can have both a cause and one or more suppressed - * exceptions: - * <pre> - * Exception in thread "main" java.lang.Exception: Main block - * at Foo3.main(Foo3.java:7) - * Suppressed: Resource$CloseFailException: Resource ID = 2 - * at Resource.close(Resource.java:26) - * at Foo3.main(Foo3.java:5) - * Suppressed: Resource$CloseFailException: Resource ID = 1 - * at Resource.close(Resource.java:26) - * at Foo3.main(Foo3.java:5) - * Caused by: java.lang.Exception: I did it - * at Foo3.main(Foo3.java:8) - * </pre> - * Likewise, a suppressed exception can have a cause: - * <pre> - * Exception in thread "main" java.lang.Exception: Main block - * at Foo4.main(Foo4.java:6) - * Suppressed: Resource2$CloseFailException: Resource ID = 1 - * at Resource2.close(Resource2.java:20) - * at Foo4.main(Foo4.java:5) - * Caused by: java.lang.Exception: Rats, you caught me - * at Resource2$CloseFailException.<init>(Resource2.java:45) - * ... 2 more - * </pre> - */ - public static void printStackTrace(Throwable _this) { - _this.printStackTrace(System.err); - } - - /** - * Prints this throwable and its backtrace to the specified print stream. - * - * @param s {@code PrintStream} to use for output - */ - public static void printStackTrace(Throwable _this, PrintStream s) { - printStackTrace(_this, new WrappedPrintStream(s)); - } - - private static void printStackTrace(Throwable _this, PrintStreamOrWriter s) { - // Guard against malicious overrides of Throwable.equals by - // using a Set with identity equality semantics. - Set<Throwable> dejaVu = - Collections.newSetFromMap(new IdentityHashMap<Throwable, Boolean>()); - dejaVu.add(_this); - - synchronized (s.lock()) { - // Print our stack trace - s.println(_this); - StackTraceElement[] trace = getOurStackTrace(_this); - for (StackTraceElement traceElement : trace) - s.println("\tat " + traceElement); - - // Print suppressed exceptions, if any - for (Throwable se : _this.getSuppressed()) - printEnclosedStackTrace(se, s, trace, SUPPRESSED_CAPTION, "\t", dejaVu); - - // Print cause, if any - Throwable ourCause = _this.getCause(); - if (ourCause != null) - printEnclosedStackTrace(ourCause, s, trace, CAUSE_CAPTION, "", dejaVu); - } - } - - /** - * Print our stack trace as an enclosed exception for the specified - * stack trace. - */ - private static void printEnclosedStackTrace(Throwable _this, PrintStreamOrWriter s, - StackTraceElement[] enclosingTrace, - String caption, - String prefix, - Set<Throwable> dejaVu) { - assert Thread.holdsLock(s.lock()); - if (dejaVu.contains(_this)) { - s.println("\t[CIRCULAR REFERENCE:" + _this + "]"); - } else { - dejaVu.add(_this); - // Compute number of frames in common between this and enclosing trace - StackTraceElement[] trace = getOurStackTrace(_this); - int m = trace.length - 1; - int n = enclosingTrace.length - 1; - while (m >= 0 && n >=0 && trace[m].equals(enclosingTrace[n])) { - m--; n--; - } - int framesInCommon = trace.length - 1 - m; - - // Print our stack trace - s.println(prefix + caption + _this); - for (int i = 0; i <= m; i++) - s.println(prefix + "\tat " + trace[i]); - if (framesInCommon != 0) - s.println(prefix + "\t... " + framesInCommon + " more"); - - // Print suppressed exceptions, if any - for (Throwable se : _this.getSuppressed()) - printEnclosedStackTrace(se, s, trace, SUPPRESSED_CAPTION, - prefix +"\t", dejaVu); - - // Print cause, if any - Throwable ourCause = _this.getCause(); - if (ourCause != null) - printEnclosedStackTrace(ourCause, s, trace, CAUSE_CAPTION, prefix, dejaVu); - } - } - - private static native StackTraceElement[] getOurStackTrace(Throwable _this); - - /** - * Prints this throwable and its backtrace to the specified - * print writer. - * - * @param s {@code PrintWriter} to use for output - * @since JDK1.1 - */ - public static void printStackTrace(Throwable _this, PrintWriter s) { - printStackTrace(_this, new WrappedPrintWriter(s)); - } - - /** - * Wrapper class for PrintStream and PrintWriter to enable a single - * implementation of printStackTrace. - */ - private abstract static class PrintStreamOrWriter { - /** Returns the object to be locked when using this StreamOrWriter */ - abstract Object lock(); - - /** Prints the specified string as a line on this StreamOrWriter */ - abstract void println(Object o); - } - - private static class WrappedPrintStream extends PrintStreamOrWriter { - private final PrintStream printStream; - - WrappedPrintStream(PrintStream printStream) { - this.printStream = printStream; - } - - Object lock() { - return printStream; - } - - void println(Object o) { - printStream.println(o); - } - } - - private static class WrappedPrintWriter extends PrintStreamOrWriter { - private final PrintWriter printWriter; - - WrappedPrintWriter(PrintWriter printWriter) { - this.printWriter = printWriter; - } - - Object lock() { - return printWriter; - } - - void println(Object o) { - printWriter.println(o); - } - } -} diff --git a/openjdk/java/lang/VMSystemProperties.java b/openjdk/java/lang/VMSystemProperties.java deleted file mode 100644 index c982e2dd..00000000 --- a/openjdk/java/lang/VMSystemProperties.java +++ /dev/null @@ -1,421 +0,0 @@ -/* - Copyright (C) 2004-2011 Jeroen Frijters - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jeroen Frijters - jeroen@frijters.net - -*/ -package java.lang; - -import java.util.Properties; -import static ikvm.internal.Util.SafeGetEnvironmentVariable; - -final class VMSystemProperties -{ - private VMSystemProperties() { } - - public static final String SPEC_TITLE = "Java Platform API Specification"; - public static final String SPEC_VERSION = "1.7"; - public static final String SPEC_VENDOR = "Oracle Corporation"; - - private static String getLibraryPath() - { - String libraryPath; - if(ikvm.internal.Util.WINDOWS) - { - // see /hotspot/src/os/windows/vm/os_windows.cpp for the comment that describes how we build the path - String windir = SafeGetEnvironmentVariable("SystemRoot"); - if(windir != null) - { - libraryPath = cli.System.IO.Path.PathSeparator + windir + "\\Sun\\Java\\bin"; - } - else - { - libraryPath = null; - } - try - { - if(false) throw new cli.System.Security.SecurityException(); - if (libraryPath == null) - { - libraryPath = cli.System.Environment.get_SystemDirectory(); - } - else - { - libraryPath += cli.System.IO.Path.PathSeparator + cli.System.Environment.get_SystemDirectory(); - } - } - catch(cli.System.Security.SecurityException _) - { - } - if(windir != null) - { - libraryPath += cli.System.IO.Path.PathSeparator + windir; - } - String path = SafeGetEnvironmentVariable("PATH"); - if(path != null) - { - libraryPath += cli.System.IO.Path.PathSeparator + path; - } - } - else if(ikvm.internal.Util.MACOSX) - { - libraryPath = "."; - } - else /* assume Linux, since that's the only other platform we support */ - { - // on Linux we have some hardcoded paths (from /hotspot/src/os/linux/vm/os_linux.cpp) - // and we can only guess the cpu arch based on bitness (that means only x86 and x64) - String cpu_arch = cli.System.IntPtr.get_Size() == 4 ? "i386" : "amd64"; - libraryPath = "/usr/java/packages/lib/" + cpu_arch + ":/lib:/usr/lib"; - String ld_library_path = SafeGetEnvironmentVariable("LD_LIBRARY_PATH"); - if(ld_library_path != null) - { - libraryPath = ld_library_path + ":" + libraryPath; - } - } - try - { - cli.System.Reflection.Assembly entryAsm = cli.System.Reflection.Assembly.GetEntryAssembly(); - // If the CLR was started by a native app (e.g. via COM interop) there is no entry assembly - if (entryAsm != null) - { - // the application (or launcher) directory is prepended to the library path - // (similar to how the JDK prepends its directory to the path) - libraryPath = new cli.System.IO.FileInfo(entryAsm.get_Location()).get_DirectoryName() + cli.System.IO.Path.PathSeparator + libraryPath; - } - } - catch(Throwable _) - { - // ignore - } - if(ikvm.internal.Util.WINDOWS) - { - libraryPath += cli.System.IO.Path.PathSeparator + "."; - } - return libraryPath; - } - - private static void initCommonProperties(Properties p) - { - p.setProperty("java.version", "1.7.0"); - p.setProperty("java.vendor", "Jeroen Frijters"); - p.setProperty("java.vendor.url", "http://ikvm.net/"); - p.setProperty("java.vendor.url.bug", "http://www.ikvm.net/bugs"); - p.setProperty("java.vm.specification.version", "1.7"); - p.setProperty("java.vm.specification.vendor", "Oracle Corporation"); - p.setProperty("java.vm.specification.name", "Java Virtual Machine Specification"); - p.setProperty("java.vm.version", PropertyConstants.java_vm_version); - p.setProperty("java.vm.vendor", "Jeroen Frijters"); - p.setProperty("java.vm.name", "IKVM.NET"); - p.setProperty("java.runtime.name", "IKVM.NET"); - p.setProperty("java.runtime.version", PropertyConstants.java_runtime_version); - p.setProperty("java.specification.version", SPEC_VERSION); - p.setProperty("java.specification.vendor", SPEC_VENDOR); - p.setProperty("java.specification.name", SPEC_TITLE); - p.setProperty("java.class.version", "51.0"); - p.setProperty("java.class.path", ""); - p.setProperty("java.library.path", getLibraryPath()); - try - { - if(false) throw new cli.System.Security.SecurityException(); - p.setProperty("java.io.tmpdir", cli.System.IO.Path.GetTempPath()); - } - catch(cli.System.Security.SecurityException _) - { - // TODO should we set another value? - p.setProperty("java.io.tmpdir", "."); - } - p.setProperty("java.ext.dirs", ""); - // NOTE os.name *must* contain "Windows" when running on Windows, because Classpath tests on that - String osname = null; - String osver = null; - cli.System.OperatingSystem os = cli.System.Environment.get_OSVersion(); - int major = os.get_Version().get_Major(); - int minor = os.get_Version().get_Minor(); - switch(os.get_Platform().Value) - { - case cli.System.PlatformID.Win32NT: - osname = "Windows NT (unknown)"; - switch(major) - { - case 3: - case 4: - osver = major + "." + minor; - osname = "Windows NT"; - break; - case 5: - switch(minor) - { - case 0: - osver = "5.0"; - osname = "Windows 2000"; - break; - case 1: - osver = "5.1"; - osname = "Windows XP"; - break; - case 2: - osver = "5.2"; - osname = "Windows 2003"; - break; - } - break; - case 6: - // since there appears to be no managed way to differentiate between Client/Server, we report client names - switch(minor) - { - case 0: - osver = "6.0"; - osname = "Windows Vista"; - break; - case 1: - osver = "6.1"; - osname = "Windows 7"; - break; - } - break; - } - break; - case cli.System.PlatformID.Win32Windows: - if(major == 4) - { - switch(minor) - { - case 0: - osver = "4.0"; - osname = "Windows 95"; - break; - case 10: - osver = "4.10"; - osname = "Windows 98"; - break; - case 90: - osver = "4.90"; - osname = "Windows Me"; - break; - } - } - break; - case cli.System.PlatformID.Unix: - if(ikvm.internal.Util.MACOSX) - { - // for back compat Mono will return PlatformID.Unix when running on the Mac, - // so we handle that explicitly here - osname = "Mac OS X"; - // HACK this tries to map the Darwin version to the OS X version - // (based on http://en.wikipedia.org/wiki/Darwin_(operating_system)#Releases) - cli.System.Version ver = cli.System.Environment.get_OSVersion().get_Version(); - osver = "10." + (ver.get_Major() - 4) + "." + ver.get_Minor(); - } - break; - } - if(osname == null) - { - osname = cli.System.Environment.get_OSVersion().ToString(); - } - if(osver == null) - { - osver = major + "." + minor; - } - p.setProperty("os.name", osname); - p.setProperty("os.version", osver); - String arch = SafeGetEnvironmentVariable("PROCESSOR_ARCHITECTURE"); - if(arch == null) - { - // we don't know, so we make a guess - if(cli.System.IntPtr.get_Size() == 4) - { - arch = ikvm.internal.Util.WINDOWS ? "x86" : "i386"; - } - else - { - arch = "amd64"; - } - } - if(arch.equals("AMD64")) - { - arch = "amd64"; - } - p.setProperty("os.arch", arch); - p.setProperty("sun.arch.data.model", "" + (cli.System.IntPtr.get_Size() * 8)); - p.setProperty("file.separator", "" + cli.System.IO.Path.DirectorySeparatorChar); - p.setProperty("file.encoding", cli.System.Text.Encoding.get_Default().get_WebName()); - p.setProperty("path.separator", "" + cli.System.IO.Path.PathSeparator); - p.setProperty("line.separator", cli.System.Environment.get_NewLine()); - try - { - if(false) throw new cli.System.Security.SecurityException(); - p.setProperty("user.name", cli.System.Environment.get_UserName()); - } - catch(cli.System.Security.SecurityException _) - { - p.setProperty("user.name", "(unknown)"); - } - String home = SafeGetEnvironmentVariable("USERPROFILE"); - if(home == null) - { - // maybe we're on *nix - home = SafeGetEnvironmentVariable("HOME"); - if(home == null) - { - // TODO maybe there is a better way - // NOTE on MS .NET this doesn't return the correct path - // (it returns "C:\\Documents and Settings\\username\\My Documents", but we really need - // "C:\\Documents and Settings\\username" to be compatible with Sun, that's why we use %USERPROFILE% if it exists) - try - { - if(false) throw new cli.System.Security.SecurityException(); - home = cli.System.Environment.GetFolderPath(cli.System.Environment.SpecialFolder.wrap(cli.System.Environment.SpecialFolder.Personal)); - } - catch(cli.System.Security.SecurityException _) - { - home = "."; - } - } - } - p.setProperty("user.home", home); - try - { - if(false) throw new cli.System.Security.SecurityException(); - p.setProperty("user.dir", cli.System.Environment.get_CurrentDirectory()); - } - catch(cli.System.Security.SecurityException _) - { - p.setProperty("user.dir", "."); - } - p.setProperty("awt.toolkit", PropertyConstants.awt_toolkit); - } - - public static void initProperties(Properties p) - { - p.setProperty("openjdk.version", PropertyConstants.openjdk_version); - String vfsroot = getVirtualFileSystemRoot(); - p.setProperty("java.home", vfsroot.substring(0, vfsroot.length() - 1)); - // the %home%\lib\endorsed directory does not exist, but neither does it on JDK 1.7 - p.setProperty("java.endorsed.dirs", vfsroot + "lib" + cli.System.IO.Path.DirectorySeparatorChar + "endorsed"); - p.setProperty("sun.boot.library.path", vfsroot + "bin"); - p.setProperty("sun.boot.class.path", getBootClassPath()); - initCommonProperties(p); - setupI18N(p); - p.setProperty("sun.cpu.endian", cli.System.BitConverter.IsLittleEndian ? "little" : "big"); - p.setProperty("file.encoding.pkg", "sun.io"); - p.setProperty("user.timezone", ""); - p.setProperty("sun.os.patch.level", cli.System.Environment.get_OSVersion().get_ServicePack()); - p.setProperty("java.vm.info", "compiled mode"); - p.setProperty("sun.nio.MaxDirectMemorySize", "-1"); - p.setProperty("java.awt.graphicsenv", PropertyConstants.java_awt_graphicsenv); - p.setProperty("java.awt.printerjob", "sun.awt.windows.WPrinterJob"); - - // TODO - // sun.cpu.isalist:=pentium_pro+mmx pentium_pro pentium+mmx pentium i486 i386 i86 - // sun.desktop:=windows - // sun.io.unicode.encoding:=UnicodeLittle - // sun.jnu.encoding:=Cp1252 - // sun.management.compiler:=HotSpot Client Compiler - try - { - // read properties from app.config - if(false) throw new cli.System.Configuration.ConfigurationException(); - cli.System.Collections.Specialized.NameValueCollection appSettings = cli.System.Configuration.ConfigurationSettings.get_AppSettings(); - cli.System.Collections.IEnumerator keys = appSettings.GetEnumerator(); - while(keys.MoveNext()) - { - String key = (String)keys.get_Current(); - if(key.startsWith("ikvm:")) - { - p.setProperty(key.substring(5), appSettings.get_Item(key)); - } - } - } - catch(cli.System.Configuration.ConfigurationException _) - { - // app.config is invalid, ignore - } - // set the properties that were specified with ikvm.runtime.Startup.setProperties() - cli.System.Collections.IDictionary props = ikvm.runtime.Startup.props; - if(props != null) - { - cli.System.Collections.IDictionaryEnumerator entries = props.GetEnumerator(); - while(entries.MoveNext()) - { - p.setProperty((String)entries.get_Key(), (String)entries.get_Value()); - } - } - } - - private static void setupI18N(Properties p) - { - String[] culture = ((cli.System.String)(Object)cli.System.Globalization.CultureInfo.get_CurrentCulture().get_Name()).Split(new char[] { '-' }); - String language; - String script; - String region; - String variant; - if (culture.length == 2) - { - language = culture[0]; - if (culture[1].length() == 4) - { - script = culture[1]; - region = ""; - } - else - { - script = ""; - region = culture[1]; - } - } - else if (culture.length == 3) - { - language = culture[0]; - script = culture[1]; - region = culture[2]; - } - else - { - language = "en"; - script = ""; - region = "US"; - } - // Norwegian - if (language.equals("nb")) - { - language = "no"; - region = "NO"; - variant = ""; - } - else if (language.equals("nn")) - { - language = "no"; - region = "NO"; - variant = "NY"; - } - else - { - variant = ""; - } - p.setProperty("user.language", language); - p.setProperty("user.country", region); - p.setProperty("user.variant", variant); - p.setProperty("user.script", script); - } - - private static native String getVirtualFileSystemRoot(); - private static native String getBootClassPath(); -} diff --git a/openjdk/java/lang/invoke/AdapterMethodHandle.java b/openjdk/java/lang/invoke/AdapterMethodHandle.java deleted file mode 100644 index b5686afa..00000000 --- a/openjdk/java/lang/invoke/AdapterMethodHandle.java +++ /dev/null @@ -1,477 +0,0 @@ -/* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Extensively modified for IKVM.NET by Jeroen Frijters - * Copyright (C) 2011 Jeroen Frijters - */ - -package java.lang.invoke; - -import sun.invoke.util.VerifyType; -import sun.invoke.util.Wrapper; -import sun.invoke.util.ValueConversions; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Collections; -import static java.lang.invoke.MethodHandleStatics.*; -import ikvm.internal.NotYetImplementedError; - -/** - * This method handle performs simple conversion or checking of a single argument. - * @author jrose - */ -class AdapterMethodHandle extends BoundMethodHandle { - - AdapterMethodHandle(MethodType type) { - super(type, null, -1); - } - AdapterMethodHandle(MethodType type, Object vmtarget) { - super(type, null, -1); - this.vmtarget = vmtarget; - } - - /** Can a JVM-level adapter directly implement the proposed - * argument conversion, as if by fixed-arity MethodHandle.asType? - */ - static boolean canConvertArgument(Class<?> src, Class<?> dst, int level) { - return true; - } - - /** - * Create a JVM-level adapter method handle to conform the given method - * handle to the similar newType, using only pairwise argument conversions. - * For each argument, convert incoming argument to the exact type needed. - * The argument conversions allowed are casting, boxing and unboxing, - * integral widening or narrowing, and floating point widening or narrowing. - * @param newType required call type - * @param target original method handle - * @param level which strength of conversion is allowed - * @return an adapter to the original handle with the desired new type, - * or the original target if the types are already identical - * or null if the adaptation cannot be made - */ - static native MethodHandle makePairwiseConvert(MethodType newType, MethodHandle target, int level); - - /* Return one plus the position of the first non-trivial difference - * between the given types. This is not a symmetric operation; - * we are considering adapting the targetType to adapterType. - * Trivial differences are those which could be ignored by the JVM - * without subverting the verifier. Otherwise, adaptable differences - * are ones for which we could create an adapter to make the type change. - * Return zero if there are no differences (other than trivial ones). - * Return 1+N if N is the only adaptable argument difference. - * Return the -2-N where N is the first of several adaptable - * argument differences. - * Return -1 if there there are differences which are not adaptable. - */ - private static int diffTypes(MethodType adapterType, - MethodType targetType, - boolean raw) { - int diff; - diff = diffReturnTypes(adapterType, targetType, raw); - if (diff != 0) return diff; - int nargs = adapterType.parameterCount(); - if (nargs != targetType.parameterCount()) - return -1; - diff = diffParamTypes(adapterType, 0, targetType, 0, nargs, raw); - //System.out.println("diff "+adapterType); - //System.out.println(" "+diff+" "+targetType); - return diff; - } - private static int diffReturnTypes(MethodType adapterType, - MethodType targetType, - boolean raw) { - Class<?> src = targetType.returnType(); - Class<?> dst = adapterType.returnType(); - if ((!raw - ? VerifyType.canPassUnchecked(src, dst) - : VerifyType.canPassRaw(src, dst) - ) > 0) - return 0; // no significant difference - if (raw && !src.isPrimitive() && !dst.isPrimitive()) - return 0; // can force a reference return (very carefully!) - //if (false) return 1; // never adaptable! - return -1; // some significant difference - } - private static int diffParamTypes(MethodType adapterType, int astart, - MethodType targetType, int tstart, - int nargs, boolean raw) { - assert(nargs >= 0); - int res = 0; - for (int i = 0; i < nargs; i++) { - Class<?> src = adapterType.parameterType(astart+i); - Class<?> dest = targetType.parameterType(tstart+i); - if ((!raw - ? VerifyType.canPassUnchecked(src, dest) - : VerifyType.canPassRaw(src, dest) - ) <= 0) { - // found a difference; is it the only one so far? - if (res != 0) - return -1-res; // return -2-i for prev. i - res = 1+i; - } - } - return res; - } - - /** Can a retyping adapter (alone) validly convert the target to newType? */ - static boolean canRetypeOnly(MethodType newType, MethodType targetType) { - return canRetype(newType, targetType, false); - } - /** Can a retyping adapter (alone) convert the target to newType? - * It is allowed to widen subword types and void to int, to make bitwise - * conversions between float/int and double/long, and to perform unchecked - * reference conversions on return. This last feature requires that the - * caller be trusted, and perform explicit cast conversions on return values. - */ - static boolean canRetypeRaw(MethodType newType, MethodType targetType) { - return canRetype(newType, targetType, true); - } - static boolean canRetype(MethodType newType, MethodType targetType, boolean raw) { - int diff = diffTypes(newType, targetType, raw); - // %%% This assert is too strong. Factor diff into VerifyType and reconcile. - assert(raw || (diff == 0) == VerifyType.isNullConversion(newType, targetType)); - return diff == 0; - } - - /** Factory method: Performs no conversions; simply retypes the adapter. - * Allows unchecked argument conversions pairwise, if they are safe. - * Returns null if not possible. - */ - static MethodHandle makeRetypeOnly(MethodType newType, MethodHandle target) { - return makeRetype(newType, target, false); - } - static MethodHandle makeRetypeRaw(MethodType newType, MethodHandle target) { - return makeRetype(newType, target, true); - } - static native MethodHandle makeRetype(MethodType newType, MethodHandle target, boolean raw); - - static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) { - MethodType type = target.type(); - int last = type.parameterCount() - 1; - if (type.parameterType(last) != arrayType) - target = target.asType(type.changeParameterType(last, arrayType)); - target = target.asFixedArity(); // make sure this attribute is turned off - return new AsVarargsCollector(target, arrayType); - } - - static class AsVarargsCollector extends AdapterMethodHandle { - final MethodHandle target; - final Class<?> arrayType; - MethodHandle cache; - - AsVarargsCollector(MethodHandle target, Class<?> arrayType) { - super(target.type()); - this.vmtarget = target.vmtarget; - this.target = target; - this.arrayType = arrayType; - this.cache = target.asCollector(arrayType, 0); - } - - @Override - public boolean isVarargsCollector() { - return true; - } - - @Override - public MethodHandle asFixedArity() { - return target; - } - - @Override - public MethodHandle asType(MethodType newType) { - MethodType type = this.type(); - int collectArg = type.parameterCount() - 1; - int newArity = newType.parameterCount(); - if (newArity == collectArg+1 && - type.parameterType(collectArg).isAssignableFrom(newType.parameterType(collectArg))) { - // if arity and trailing parameter are compatible, do normal thing - return super.asType(newType); - } - // check cache - if (cache.type().parameterCount() == newArity) - return cache.asType(newType); - // build and cache a collector - int arrayLength = newArity - collectArg; - MethodHandle collector; - try { - collector = target.asCollector(arrayType, arrayLength); - } catch (IllegalArgumentException ex) { - throw new WrongMethodTypeException("cannot build collector"); - } - cache = collector; - return collector.asType(newType); - } - } - - /** Can a checkcast adapter validly convert the target to newType? - * The JVM supports all kind of reference casts, even silly ones. - */ - static boolean canCheckCast(MethodType newType, MethodType targetType, - int arg, Class<?> castType) { - Class<?> src = newType.parameterType(arg); - Class<?> dst = targetType.parameterType(arg); - if (!canCheckCast(src, castType) - || !VerifyType.isNullConversion(castType, dst)) - return false; - int diff = diffTypes(newType, targetType, false); - return (diff == arg+1) || (diff == 0); // arg is sole non-trivial diff - } - /** Can an primitive conversion adapter validly convert src to dst? */ - static boolean canCheckCast(Class<?> src, Class<?> dst) { - return (!src.isPrimitive() && !dst.isPrimitive()); - } - - /** Factory method: Forces a cast at the given argument. - * The castType is the target of the cast, and can be any type - * with a null conversion to the corresponding target parameter. - * Return null if this cannot be done. - */ - static MethodHandle makeCheckCast(MethodType newType, MethodHandle target, - int arg, Class<?> castType) { - if (!canCheckCast(newType, target.type(), arg, castType)) - return null; - throw new NotYetImplementedError(); - } - - /** Can an adapter simply drop arguments to convert the target to newType? */ - static boolean canDropArguments(MethodType newType, MethodType targetType, - int dropArgPos, int dropArgCount) { - if (dropArgCount == 0) - return canRetypeOnly(newType, targetType); - if (diffReturnTypes(newType, targetType, false) != 0) - return false; - int nptypes = newType.parameterCount(); - // parameter types must be the same up to the drop point - if (dropArgPos != 0 && diffParamTypes(newType, 0, targetType, 0, dropArgPos, false) != 0) - return false; - int afterPos = dropArgPos + dropArgCount; - int afterCount = nptypes - afterPos; - if (dropArgPos < 0 || dropArgPos >= nptypes || - dropArgCount < 1 || afterPos > nptypes || - targetType.parameterCount() != nptypes - dropArgCount) - return false; - // parameter types after the drop point must also be the same - if (afterCount != 0 && diffParamTypes(newType, afterPos, targetType, dropArgPos, afterCount, false) != 0) - return false; - return true; - } - - /** Factory method: Drop selected arguments. - * Allow unchecked retyping of remaining arguments, pairwise. - * Return null if this is not possible. - */ - static MethodHandle makeDropArguments(MethodType newType, MethodHandle target, - int dropArgPos, int dropArgCount) { - if (dropArgCount == 0) - return makeRetypeOnly(newType, target); - if (!canDropArguments(newType, target.type(), dropArgPos, dropArgCount)) - return null; - int[] permute = new int[target.type().parameterCount()]; - for (int i = 0, arg = 0; i < permute.length; i++) { - if (arg == dropArgPos) - arg += dropArgCount; - permute[i] = arg++; - } - return MethodHandleImpl.permuteArguments(target, newType, target.type(), permute); - } - - /** Can an adapter duplicate an argument to convert the target to newType? */ - static boolean canDupArguments(MethodType newType, MethodType targetType, - int dupArgPos, int dupArgCount) { - if (diffReturnTypes(newType, targetType, false) != 0) - return false; - int nptypes = newType.parameterCount(); - if (dupArgCount < 0 || dupArgPos + dupArgCount > nptypes) - return false; - if (targetType.parameterCount() != nptypes + dupArgCount) - return false; - // parameter types must be the same up to the duplicated arguments - if (diffParamTypes(newType, 0, targetType, 0, nptypes, false) != 0) - return false; - // duplicated types must be, well, duplicates - if (diffParamTypes(newType, dupArgPos, targetType, nptypes, dupArgCount, false) != 0) - return false; - return true; - } - - /** Factory method: Duplicate the selected argument. - * Return null if this is not possible. - */ - static MethodHandle makeDupArguments(MethodType newType, MethodHandle target, - int dupArgPos, int dupArgCount) { - if (!canDupArguments(newType, target.type(), dupArgPos, dupArgCount)) - return null; - if (dupArgCount == 0) - return target; - // in arglist: [0: ...keep1 | dpos: dup... | dpos+dcount: keep2... ] - // out arglist: [0: ...keep1 | dpos: dup... | dpos+dcount: keep2... | dup... ] - throw new NotYetImplementedError(); - } - - /** Can an adapter swap two arguments to convert the target to newType? */ - static boolean canSwapArguments(MethodType newType, MethodType targetType, - int swapArg1, int swapArg2) { - if (diffReturnTypes(newType, targetType, false) != 0) - return false; - if (swapArg1 >= swapArg2) return false; // caller resp - int nptypes = newType.parameterCount(); - if (targetType.parameterCount() != nptypes) - return false; - if (swapArg1 < 0 || swapArg2 >= nptypes) - return false; - if (diffParamTypes(newType, 0, targetType, 0, swapArg1, false) != 0) - return false; - if (diffParamTypes(newType, swapArg1, targetType, swapArg2, 1, false) != 0) - return false; - if (diffParamTypes(newType, swapArg1+1, targetType, swapArg1+1, swapArg2-swapArg1-1, false) != 0) - return false; - if (diffParamTypes(newType, swapArg2, targetType, swapArg1, 1, false) != 0) - return false; - if (diffParamTypes(newType, swapArg2+1, targetType, swapArg2+1, nptypes-swapArg2-1, false) != 0) - return false; - return true; - } - - /** Factory method: Swap the selected arguments. - * Return null if this is not possible. - */ - static MethodHandle makeSwapArguments(MethodType newType, MethodHandle target, - int swapArg1, int swapArg2) { - if (swapArg1 == swapArg2) - return target; - if (swapArg1 > swapArg2) { int t = swapArg1; swapArg1 = swapArg2; swapArg2 = t; } - if (!canSwapArguments(newType, target.type(), swapArg1, swapArg2)) - return null; - // in arglist: [0: ...keep1 | pos1: a1 | pos1+1: keep2... | pos2: a2 | pos2+1: keep3... ] - // out arglist: [0: ...keep1 | pos1: a2 | pos1+1: keep2... | pos2: a1 | pos2+1: keep3... ] - throw new NotYetImplementedError(); - } - - static int positiveRotation(int argCount, int rotateBy) { - assert(argCount > 0); - if (rotateBy >= 0) { - if (rotateBy < argCount) - return rotateBy; - return rotateBy % argCount; - } else if (rotateBy >= -argCount) { - return rotateBy + argCount; - } else { - return (-1-((-1-rotateBy) % argCount)) + argCount; - } - } - - final static int MAX_ARG_ROTATION = 1; - - /** Can an adapter rotate arguments to convert the target to newType? */ - static boolean canRotateArguments(MethodType newType, MethodType targetType, - int firstArg, int argCount, int rotateBy) { - rotateBy = positiveRotation(argCount, rotateBy); - if (rotateBy == 0) return false; // no rotation - if (rotateBy > MAX_ARG_ROTATION && rotateBy < argCount - MAX_ARG_ROTATION) - return false; // too many argument positions - // Rotate incoming args right N to the out args, N in 1..(argCouunt-1). - if (diffReturnTypes(newType, targetType, false) != 0) - return false; - int nptypes = newType.parameterCount(); - if (targetType.parameterCount() != nptypes) - return false; - if (firstArg < 0 || firstArg >= nptypes) return false; - int argLimit = firstArg + argCount; - if (argLimit > nptypes) return false; - if (diffParamTypes(newType, 0, targetType, 0, firstArg, false) != 0) - return false; - int newChunk1 = argCount - rotateBy, newChunk2 = rotateBy; - // swap new chunk1 with target chunk2 - if (diffParamTypes(newType, firstArg, targetType, argLimit-newChunk1, newChunk1, false) != 0) - return false; - // swap new chunk2 with target chunk1 - if (diffParamTypes(newType, firstArg+newChunk1, targetType, firstArg, newChunk2, false) != 0) - return false; - return true; - } - - /** Factory method: Rotate the selected argument range. - * Return null if this is not possible. - */ - static MethodHandle makeRotateArguments(MethodType newType, MethodHandle target, - int firstArg, int argCount, int rotateBy) { - rotateBy = positiveRotation(argCount, rotateBy); - if (!canRotateArguments(newType, target.type(), firstArg, argCount, rotateBy)) - return null; - throw new NotYetImplementedError(); - } - - /** Can an adapter spread an argument to convert the target to newType? */ - static boolean canSpreadArguments(MethodType newType, MethodType targetType, - Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) { - if (diffReturnTypes(newType, targetType, false) != 0) - return false; - int nptypes = newType.parameterCount(); - // parameter types must be the same up to the spread point - if (spreadArgPos != 0 && diffParamTypes(newType, 0, targetType, 0, spreadArgPos, false) != 0) - return false; - int afterPos = spreadArgPos + spreadArgCount; - int afterCount = nptypes - (spreadArgPos + 1); - if (spreadArgPos < 0 || spreadArgPos >= nptypes || - spreadArgCount < 0 || - targetType.parameterCount() != afterPos + afterCount) - return false; - // parameter types after the spread point must also be the same - if (afterCount != 0 && diffParamTypes(newType, spreadArgPos+1, targetType, afterPos, afterCount, false) != 0) - return false; - // match the array element type to the spread arg types - Class<?> rawSpreadArgType = newType.parameterType(spreadArgPos); - if (rawSpreadArgType != spreadArgType && !canCheckCast(rawSpreadArgType, spreadArgType)) - return false; - for (int i = 0; i < spreadArgCount; i++) { - Class<?> src = VerifyType.spreadArgElementType(spreadArgType, i); - Class<?> dst = targetType.parameterType(spreadArgPos + i); - if (src == null || !canConvertArgument(src, dst, 1)) - return false; - } - return true; - } - - - /** Factory method: Spread selected argument. */ - static native MethodHandle makeSpreadArguments(MethodType newType, MethodHandle target, Class<?> spreadArgType, int spreadArgPos, int spreadArgCount); - - /** Can an adapter collect a series of arguments, replacing them by zero or one results? */ - static boolean canCollectArguments(MethodType targetType, - MethodType collectorType, int collectArgPos, boolean retainOriginalArgs) { - int collectArgCount = collectorType.parameterCount(); - Class<?> rtype = collectorType.returnType(); - assert(rtype == void.class || targetType.parameterType(collectArgPos) == rtype) - // [(Object)Object[], (Object[])Object[], 0, 1] - : Arrays.asList(targetType, collectorType, collectArgPos, collectArgCount) - ; - return true; - } - - /** Factory method: Collect or filter selected argument(s). */ - static native MethodHandle makeCollectArguments(MethodHandle target, MethodHandle collector, int collectArgPos, boolean retainOriginalArgs); -} diff --git a/openjdk/java/lang/invoke/BoundMethodHandle.java b/openjdk/java/lang/invoke/BoundMethodHandle.java deleted file mode 100644 index 6098ca3f..00000000 --- a/openjdk/java/lang/invoke/BoundMethodHandle.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Extensively modified for IKVM.NET by Jeroen Frijters - * Copyright (C) 2011 Jeroen Frijters - */ - -package java.lang.invoke; - -import sun.invoke.util.VerifyType; -import sun.invoke.util.Wrapper; -import static java.lang.invoke.MethodHandleStatics.*; - -/** - * The flavor of method handle which emulates an invoke instruction - * on a predetermined argument. The JVM dispatches to the correct method - * when the handle is created, not when it is invoked. - * @author jrose - */ -class BoundMethodHandle extends MethodHandle { - //MethodHandle vmtarget; // next BMH or final DMH or methodOop - private final Object argument; // argument to insert - private final int vmargslot; // position at which it is inserted - - // Constructors in this class *must* be package scoped or private. - - /** Bind a direct MH to its receiver (or first ref. argument). - * The JVM will pre-dispatch the MH if it is not already static. - */ - /*non-public*/ BoundMethodHandle(DirectMethodHandle mh, Object argument) { - super(mh.type().dropParameterTypes(0, 1)); - // check the type now, once for all: - this.argument = checkReferenceArgument(argument, mh, 0); - this.vmargslot = this.type().parameterSlotCount(); - initTarget(mh, 0); - } - - /** Insert an argument into an arbitrary method handle. - * If argnum is zero, inserts the first argument, etc. - * The argument type must be a reference. - */ - /*non-public*/ BoundMethodHandle(MethodHandle mh, Object argument, int argnum) { - this(mh.type().dropParameterTypes(argnum, argnum+1), - mh, argument, argnum); - } - - /** Insert an argument into an arbitrary method handle. - * If argnum is zero, inserts the first argument, etc. - */ - /*non-public*/ BoundMethodHandle(MethodType type, MethodHandle mh, Object argument, int argnum) { - super(type); - if (mh.type().parameterType(argnum).isPrimitive()) - this.argument = bindPrimitiveArgument(argument, mh, argnum); - else { - this.argument = checkReferenceArgument(argument, mh, argnum); - } - this.vmargslot = type.parameterSlotDepth(argnum); - initTarget(mh, argnum); - } - - private void initTarget(MethodHandle mh, int argnum) { - vmtarget = createDelegate(type(), mh, argnum, argument); - } - - private static native Object createDelegate(MethodType newType, MethodHandle mh, int argnum, Object argument); - - /** For the AdapterMethodHandle subclass. - */ - /*non-public*/ BoundMethodHandle(MethodType type, Object argument, int vmargslot) { - super(type); - this.argument = argument; - this.vmargslot = vmargslot; - assert(this instanceof AdapterMethodHandle); - } - - /** Initialize the current object as a self-bound method handle, binding it - * as the first argument of the method handle {@code entryPoint}. - * The invocation type of the resulting method handle will be the - * same as {@code entryPoint}, except that the first argument - * type will be dropped. - */ - /*non-public*/ BoundMethodHandle(MethodHandle entryPoint) { - super(entryPoint.type().dropParameterTypes(0, 1)); - this.argument = this; // kludge; get rid of - this.vmargslot = this.type().parameterSlotDepth(0); - initTarget(entryPoint, 0); - } - - /** Make sure the given {@code argument} can be used as {@code argnum}-th - * parameter of the given method handle {@code mh}, which must be a reference. - * <p> - * If this fails, throw a suitable {@code WrongMethodTypeException}, - * which will prevent the creation of an illegally typed bound - * method handle. - */ - final static Object checkReferenceArgument(Object argument, MethodHandle mh, int argnum) { - Class<?> ptype = mh.type().parameterType(argnum); - if (ptype.isPrimitive()) { - // fail - } else if (argument == null) { - return null; - } else if (VerifyType.isNullReferenceConversion(argument.getClass(), ptype)) { - return argument; - } - throw badBoundArgumentException(argument, mh, argnum); - } - - /** Make sure the given {@code argument} can be used as {@code argnum}-th - * parameter of the given method handle {@code mh}, which must be a primitive. - * <p> - * If this fails, throw a suitable {@code WrongMethodTypeException}, - * which will prevent the creation of an illegally typed bound - * method handle. - */ - final static Object bindPrimitiveArgument(Object argument, MethodHandle mh, int argnum) { - Class<?> ptype = mh.type().parameterType(argnum); - Wrapper wrap = Wrapper.forPrimitiveType(ptype); - Object zero = wrap.zero(); - if (zero == null) { - // fail - } else if (argument == null) { - if (ptype != int.class && wrap.isSubwordOrInt()) - return Integer.valueOf(0); - else - return zero; - } else if (VerifyType.isNullReferenceConversion(argument.getClass(), zero.getClass())) { - if (ptype != int.class && wrap.isSubwordOrInt()) - return Wrapper.INT.wrap(argument); - else - return argument; - } - throw badBoundArgumentException(argument, mh, argnum); - } - - final static RuntimeException badBoundArgumentException(Object argument, MethodHandle mh, int argnum) { - String atype = (argument == null) ? "null" : argument.getClass().toString(); - return new ClassCastException("cannot bind "+atype+" argument to parameter #"+argnum+" of "+mh.type()); - } -} diff --git a/openjdk/java/lang/invoke/CallSite.java b/openjdk/java/lang/invoke/CallSite.java deleted file mode 100644 index 9b07446a..00000000 --- a/openjdk/java/lang/invoke/CallSite.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Extensively modified for IKVM.NET by Jeroen Frijters - * Copyright (C) 2011 Jeroen Frijters - */ - -package java.lang.invoke; - -import sun.invoke.empty.Empty; -import sun.misc.Unsafe; -import static java.lang.invoke.MethodHandleStatics.*; -import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; - -/** - * A {@code CallSite} is a holder for a variable {@link MethodHandle}, - * which is called its {@code target}. - * An {@code invokedynamic} instruction linked to a {@code CallSite} delegates - * all calls to the site's current target. - * A {@code CallSite} may be associated with several {@code invokedynamic} - * instructions, or it may be "free floating", associated with none. - * In any case, it may be invoked through an associated method handle - * called its {@linkplain #dynamicInvoker dynamic invoker}. - * <p> - * {@code CallSite} is an abstract class which does not allow - * direct subclassing by users. It has three immediate, - * concrete subclasses that may be either instantiated or subclassed. - * <ul> - * <li>If a mutable target is not required, an {@code invokedynamic} instruction - * may be permanently bound by means of a {@linkplain ConstantCallSite constant call site}. - * <li>If a mutable target is required which has volatile variable semantics, - * because updates to the target must be immediately and reliably witnessed by other threads, - * a {@linkplain VolatileCallSite volatile call site} may be used. - * <li>Otherwise, if a mutable target is required, - * a {@linkplain MutableCallSite mutable call site} may be used. - * </ul> - * <p> - * A non-constant call site may be <em>relinked</em> by changing its target. - * The new target must have the same {@linkplain MethodHandle#type() type} - * as the previous target. - * Thus, though a call site can be relinked to a series of - * successive targets, it cannot change its type. - * <p> - * Here is a sample use of call sites and bootstrap methods which links every - * dynamic call site to print its arguments: -<blockquote><pre><!-- see indy-demo/src/PrintArgsDemo.java --> -static void test() throws Throwable { - // THE FOLLOWING LINE IS PSEUDOCODE FOR A JVM INSTRUCTION - InvokeDynamic[#bootstrapDynamic].baz("baz arg", 2, 3.14); -} -private static void printArgs(Object... args) { - System.out.println(java.util.Arrays.deepToString(args)); -} -private static final MethodHandle printArgs; -static { - MethodHandles.Lookup lookup = MethodHandles.lookup(); - Class thisClass = lookup.lookupClass(); // (who am I?) - printArgs = lookup.findStatic(thisClass, - "printArgs", MethodType.methodType(void.class, Object[].class)); -} -private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String name, MethodType type) { - // ignore caller and name, but match the type: - return new ConstantCallSite(printArgs.asType(type)); -} -</pre></blockquote> - * @author John Rose, JSR 292 EG - */ -abstract -public class CallSite { - - interface IndyCallSite { - void setTarget(Object target); - } - - // The actual payload of this call site: - /*package-private*/ - volatile MethodHandle target; - final IndyCallSite ics; - - /** - * Make a blank call site object with the given method type. - * An initial target method is supplied which will throw - * an {@link IllegalStateException} if called. - * <p> - * Before this {@code CallSite} object is returned from a bootstrap method, - * it is usually provided with a more useful target method, - * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}. - * @throws NullPointerException if the proposed type is null - */ - /*package-private*/ - CallSite(MethodType type) { - this(type.invokers().uninitializedCallSite()); - } - - /** - * Make a call site object equipped with an initial target method handle. - * @param target the method handle which will be the initial target of the call site - * @throws NullPointerException if the proposed target is null - */ - /*package-private*/ - CallSite(MethodHandle target) { - target.getClass(); // null check - ics = createIndyCallSite(target.vmtarget); - setTargetNormal(target); - } - - private static native IndyCallSite createIndyCallSite(Object target); - - final void setTargetNormal(MethodHandle target) { - this.target = target; - ics.setTarget(target.vmtarget); - } - - final void setTargetVolatile(MethodHandle target) { - synchronized(ics) { - setTargetNormal(target); - } - } - - final MethodHandle getTargetVolatile() { - synchronized(ics) { - return target; - } - } - - /** - * Make a call site object equipped with an initial target method handle. - * @param targetType the desired type of the call site - * @param createTargetHook a hook which will bind the call site to the target method handle - * @throws WrongMethodTypeException if the hook cannot be invoked on the required arguments, - * or if the target returned by the hook is not of the given {@code targetType} - * @throws NullPointerException if the hook returns a null value - * @throws ClassCastException if the hook returns something other than a {@code MethodHandle} - * @throws Throwable anything else thrown by the the hook function - */ - /*package-private*/ - CallSite(MethodType targetType, MethodHandle createTargetHook) throws Throwable { - this(targetType); - ConstantCallSite selfCCS = (ConstantCallSite) this; - MethodHandle boundTarget = (MethodHandle) createTargetHook.invokeWithArguments(selfCCS); - checkTargetChange(this.target, boundTarget); - setTargetNormal(boundTarget); - } - - /** - * Returns the type of this call site's target. - * Although targets may change, any call site's type is permanent, and can never change to an unequal type. - * The {@code setTarget} method enforces this invariant by refusing any new target that does - * not have the previous target's type. - * @return the type of the current target, which is also the type of any future target - */ - public MethodType type() { - // warning: do not call getTarget here, because CCS.getTarget can throw IllegalStateException - return target.type(); - } - - /** - * Returns the target method of the call site, according to the - * behavior defined by this call site's specific class. - * The immediate subclasses of {@code CallSite} document the - * class-specific behaviors of this method. - * - * @return the current linkage state of the call site, its target method handle - * @see ConstantCallSite - * @see VolatileCallSite - * @see #setTarget - * @see ConstantCallSite#getTarget - * @see MutableCallSite#getTarget - * @see VolatileCallSite#getTarget - */ - public abstract MethodHandle getTarget(); - - /** - * Updates the target method of this call site, according to the - * behavior defined by this call site's specific class. - * The immediate subclasses of {@code CallSite} document the - * class-specific behaviors of this method. - * <p> - * The type of the new target must be {@linkplain MethodType#equals equal to} - * the type of the old target. - * - * @param newTarget the new target - * @throws NullPointerException if the proposed new target is null - * @throws WrongMethodTypeException if the proposed new target - * has a method type that differs from the previous target - * @see CallSite#getTarget - * @see ConstantCallSite#setTarget - * @see MutableCallSite#setTarget - * @see VolatileCallSite#setTarget - */ - public abstract void setTarget(MethodHandle newTarget); - - void checkTargetChange(MethodHandle oldTarget, MethodHandle newTarget) { - MethodType oldType = oldTarget.type(); - MethodType newType = newTarget.type(); // null check! - if (!newType.equals(oldType)) - throw wrongTargetType(newTarget, oldType); - } - - private static WrongMethodTypeException wrongTargetType(MethodHandle target, MethodType type) { - return new WrongMethodTypeException(String.valueOf(target)+" should be of type "+type); - } - - /** - * Produces a method handle equivalent to an invokedynamic instruction - * which has been linked to this call site. - * <p> - * This method is equivalent to the following code: - * <blockquote><pre> - * MethodHandle getTarget, invoker, result; - * getTarget = MethodHandles.publicLookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class)); - * invoker = MethodHandles.exactInvoker(this.type()); - * result = MethodHandles.foldArguments(invoker, getTarget) - * </pre></blockquote> - * - * @return a method handle which always invokes this call site's current target - */ - public abstract MethodHandle dynamicInvoker(); - - /*non-public*/ MethodHandle makeDynamicInvoker() { - MethodHandle getTarget = MethodHandleImpl.bindReceiver(GET_TARGET, this); - MethodHandle invoker = MethodHandles.exactInvoker(this.type()); - return MethodHandles.foldArguments(invoker, getTarget); - } - - private static final MethodHandle GET_TARGET; - static { - try { - GET_TARGET = IMPL_LOOKUP. - findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class)); - } catch (ReflectiveOperationException ignore) { - throw new InternalError(); - } - } - - /** This guy is rolled into the default target if a MethodType is supplied to the constructor. */ - /*package-private*/ - static Empty uninitializedCallSite() { - throw new IllegalStateException("uninitialized call site"); - } -} diff --git a/openjdk/java/lang/invoke/ConstantCallSite.java b/openjdk/java/lang/invoke/ConstantCallSite.java deleted file mode 100644 index 2d9fedec..00000000 --- a/openjdk/java/lang/invoke/ConstantCallSite.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang.invoke; - -/** - * A {@code ConstantCallSite} is a {@link CallSite} whose target is permanent, and can never be changed. - * An {@code invokedynamic} instruction linked to a {@code ConstantCallSite} is permanently - * bound to the call site's target. - * @author John Rose, JSR 292 EG - */ -public class ConstantCallSite extends CallSite { - private final boolean isFrozen; - - /** - * Creates a call site with a permanent target. - * @param target the target to be permanently associated with this call site - * @throws NullPointerException if the proposed target is null - */ - public ConstantCallSite(MethodHandle target) { - super(target); - isFrozen = true; - } - - /** - * Creates a call site with a permanent target, possibly bound to the call site itself. - * <p> - * During construction of the call site, the {@code createTargetHook} is invoked to - * produce the actual target, as if by a call of the form - * {@code (MethodHandle) createTargetHook.invoke(this)}. - * <p> - * Note that user code cannot perform such an action directly in a subclass constructor, - * since the target must be fixed before the {@code ConstantCallSite} constructor returns. - * <p> - * The hook is said to bind the call site to a target method handle, - * and a typical action would be {@code someTarget.bindTo(this)}. - * However, the hook is free to take any action whatever, - * including ignoring the call site and returning a constant target. - * <p> - * The result returned by the hook must be a method handle of exactly - * the same type as the call site. - * <p> - * While the hook is being called, the new {@code ConstantCallSite} - * object is in a partially constructed state. - * In this state, - * a call to {@code getTarget}, or any other attempt to use the target, - * will result in an {@code IllegalStateException}. - * It is legal at all times to obtain the call site's type using the {@code type} method. - * - * @param targetType the type of the method handle to be permanently associated with this call site - * @param createTargetHook a method handle to invoke (on the call site) to produce the call site's target - * @throws WrongMethodTypeException if the hook cannot be invoked on the required arguments, - * or if the target returned by the hook is not of the given {@code targetType} - * @throws NullPointerException if the hook returns a null value - * @throws ClassCastException if the hook returns something other than a {@code MethodHandle} - * @throws Throwable anything else thrown by the the hook function - */ - protected ConstantCallSite(MethodType targetType, MethodHandle createTargetHook) throws Throwable { - super(targetType, createTargetHook); - isFrozen = true; - } - - /** - * Returns the target method of the call site, which behaves - * like a {@code final} field of the {@code ConstantCallSite}. - * That is, the the target is always the original value passed - * to the constructor call which created this instance. - * - * @return the immutable linkage state of this call site, a constant method handle - * @throws IllegalStateException if the {@code ConstantCallSite} constructor has not completed - */ - @Override public final MethodHandle getTarget() { - if (!isFrozen) throw new IllegalStateException(); - return target; - } - - /** - * Always throws an {@link UnsupportedOperationException}. - * This kind of call site cannot change its target. - * @param ignore a new target proposed for the call site, which is ignored - * @throws UnsupportedOperationException because this kind of call site cannot change its target - */ - @Override public final void setTarget(MethodHandle ignore) { - throw new UnsupportedOperationException(); - } - - /** - * Returns this call site's permanent target. - * Since that target will never change, this is a correct implementation - * of {@link CallSite#dynamicInvoker CallSite.dynamicInvoker}. - * @return the immutable linkage state of this call site, a constant method handle - * @throws IllegalStateException if the {@code ConstantCallSite} constructor has not completed - */ - @Override - public final MethodHandle dynamicInvoker() { - return getTarget(); - } -} diff --git a/openjdk/java/lang/invoke/DirectMethodHandle.java b/openjdk/java/lang/invoke/DirectMethodHandle.java deleted file mode 100644 index 23a55dce..00000000 --- a/openjdk/java/lang/invoke/DirectMethodHandle.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang.invoke; - -/** - * The flavor of method handle which emulates invokespecial or invokestatic. - * @author jrose - */ -class DirectMethodHandle extends MethodHandle { - //inherited oop vmtarget; // methodOop or virtual class/interface oop - - // Constructors in this class *must* be package scoped or private. - DirectMethodHandle(MethodType mtype, MemberName m, boolean doDispatch, Class<?> lookupClass) { - super(mtype); - - assert(m.isMethod() || !doDispatch && m.isConstructor()); - if (!m.isResolved()) - throw new InternalError(); - - vmtarget = createDelegate(mtype, m, doDispatch, lookupClass); - } - - private static native Object createDelegate(MethodType type, MemberName m, boolean doDispatch, Class<?> lookupClass); - - boolean isValid() { - return vmtarget != null; - } -} diff --git a/openjdk/java/lang/invoke/MethodHandleImpl.java b/openjdk/java/lang/invoke/MethodHandleImpl.java deleted file mode 100644 index 76c41aa0..00000000 --- a/openjdk/java/lang/invoke/MethodHandleImpl.java +++ /dev/null @@ -1,740 +0,0 @@ -/* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Extensively modified for IKVM.NET by Jeroen Frijters - * Copyright (C) 2011 Jeroen Frijters - */ - -package java.lang.invoke; - -import sun.invoke.util.VerifyType; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import sun.invoke.empty.Empty; -import sun.invoke.util.ValueConversions; -import sun.invoke.util.Wrapper; -import sun.misc.Unsafe; -import static java.lang.invoke.MethodHandleStatics.*; -import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; - -/** - * Trusted implementation code for MethodHandle. - * @author jrose - */ -/*non-public*/ abstract class MethodHandleImpl { - /// Factory methods to create method handles: - - private static final MemberName.Factory LOOKUP = MemberName.Factory.INSTANCE; - - static void initStatics() { - // Trigger preceding sequence. - } - - /** Look up a given method. - * Callable only from sun.invoke and related packages. - * <p> - * The resulting method handle type will be of the given type, - * with a receiver type {@code rcvc} prepended if the member is not static. - * <p> - * Access checks are made as of the given lookup class. - * In particular, if the method is protected and {@code defc} is in a - * different package from the lookup class, then {@code rcvc} must be - * the lookup class or a subclass. - * @param token Proof that the lookup class has access to this package. - * @param member Resolved method or constructor to call. - * @param name Name of the desired method. - * @param rcvc Receiver type of desired non-static method (else null) - * @param doDispatch whether the method handle will test the receiver type - * @param lookupClass access-check relative to this class - * @return a direct handle to the matching method - * @throws IllegalAccessException if the given method cannot be accessed by the lookup class - */ - static - MethodHandle findMethod(MemberName method, - boolean doDispatch, Class<?> lookupClass) throws IllegalAccessException { - MethodType mtype = method.getMethodType(); - if (!method.isStatic()) { - // adjust the advertised receiver type to be exactly the one requested - // (in the case of invokespecial, this will be the calling class) - Class<?> recvType = method.getDeclaringClass(); - mtype = mtype.insertParameterTypes(0, recvType); - } - DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass); - if (!mh.isValid()) - throw method.makeAccessException("no direct method handle", lookupClass); - assert(mh.type() == mtype); - if (!method.isVarargs()) - return mh; - int argc = mtype.parameterCount(); - if (argc != 0) { - Class<?> arrayType = mtype.parameterType(argc-1); - if (arrayType.isArray()) - return AdapterMethodHandle.makeVarargsCollector(mh, arrayType); - } - throw method.makeAccessException("cannot make variable arity", null); - } - - static - MethodHandle makeAllocator(MethodHandle rawConstructor) { - MethodType rawConType = rawConstructor.type(); - Class<?> allocateClass = rawConType.parameterType(0); - // Wrap the raw (unsafe) constructor with the allocation of a suitable object. - // allocator(arg...) - // [fold]=> cookedConstructor(obj=allocate(C), arg...) - // [dup,collect]=> identity(obj, void=rawConstructor(obj, arg...)) - MethodHandle returner = MethodHandles.identity(allocateClass); - MethodType ctype = rawConType.insertParameterTypes(0, allocateClass).changeReturnType(allocateClass); - MethodHandle cookedConstructor = AdapterMethodHandle.makeCollectArguments(returner, rawConstructor, 1, false); - assert(cookedConstructor.type().equals(ctype)); - ctype = ctype.dropParameterTypes(0, 1); - cookedConstructor = AdapterMethodHandle.makeCollectArguments(cookedConstructor, returner, 0, true); - MethodHandle allocator = new AllocateObject(allocateClass); - // allocate() => new C(void) - assert(allocator.type().equals(MethodType.methodType(allocateClass))); - ctype = ctype.dropParameterTypes(0, 1); - MethodHandle fold = foldArguments(cookedConstructor, ctype, 0, allocator); - return fold; - } - - static final class AllocateObject<C> extends BoundMethodHandle { - private static final Unsafe unsafe = Unsafe.getUnsafe(); - - private final Class<C> allocateClass; - - // for allocation only: - private AllocateObject(Class<C> allocateClass) { - super(ALLOCATE.asType(MethodType.methodType(allocateClass, AllocateObject.class))); - this.allocateClass = allocateClass; - } - @SuppressWarnings("unchecked") - private C allocate() throws InstantiationException { - return (C) unsafe.allocateInstance(allocateClass); - } - static final MethodHandle ALLOCATE; - static { - try { - ALLOCATE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "allocate", MethodType.genericMethodType(0)); - } catch (ReflectiveOperationException ex) { - throw uncaughtException(ex); - } - } - } - - static - MethodHandle accessField(MemberName member, boolean isSetter, - Class<?> lookupClass) { - // Use sun. misc.Unsafe to dig up the dirt on the field. - MethodHandle mh = new FieldAccessor(member, isSetter); - return mh; - } - - static - MethodHandle accessArrayElement(Class<?> arrayClass, boolean isSetter) { - if (!arrayClass.isArray()) - throw newIllegalArgumentException("not an array: "+arrayClass); - Class<?> elemClass = arrayClass.getComponentType(); - MethodHandle[] mhs = FieldAccessor.ARRAY_CACHE.get(elemClass); - if (mhs == null) { - if (!FieldAccessor.doCache(elemClass)) - return FieldAccessor.ahandle(arrayClass, isSetter); - mhs = new MethodHandle[] { - FieldAccessor.ahandle(arrayClass, false), - FieldAccessor.ahandle(arrayClass, true) - }; - if (mhs[0].type().parameterType(0) == Class.class) { - mhs[0] = mhs[0].bindTo(elemClass); - mhs[1] = mhs[1].bindTo(elemClass); - } - synchronized (FieldAccessor.ARRAY_CACHE) {} // memory barrier - FieldAccessor.ARRAY_CACHE.put(elemClass, mhs); - } - return mhs[isSetter ? 1 : 0]; - } - - static final class FieldAccessor<C,V> extends BoundMethodHandle { - private static final Unsafe unsafe = Unsafe.getUnsafe(); - final Object base; // for static refs only - final long offset; - final String name; - - FieldAccessor(MemberName field, boolean isSetter) { - super(fhandle(field.getDeclaringClass(), field.getFieldType(), isSetter, field.isStatic())); - this.offset = fieldOffset(field); - this.name = field.getName(); - this.base = null; - } - @Override - String debugString() { return addTypeString(name, this); } - - int getFieldI(C obj) { return unsafe.getInt(obj, offset); } - void setFieldI(C obj, int x) { unsafe.putInt(obj, offset, x); } - long getFieldJ(C obj) { return unsafe.getLong(obj, offset); } - void setFieldJ(C obj, long x) { unsafe.putLong(obj, offset, x); } - float getFieldF(C obj) { return unsafe.getFloat(obj, offset); } - void setFieldF(C obj, float x) { unsafe.putFloat(obj, offset, x); } - double getFieldD(C obj) { return unsafe.getDouble(obj, offset); } - void setFieldD(C obj, double x) { unsafe.putDouble(obj, offset, x); } - boolean getFieldZ(C obj) { return unsafe.getBoolean(obj, offset); } - void setFieldZ(C obj, boolean x) { unsafe.putBoolean(obj, offset, x); } - byte getFieldB(C obj) { return unsafe.getByte(obj, offset); } - void setFieldB(C obj, byte x) { unsafe.putByte(obj, offset, x); } - short getFieldS(C obj) { return unsafe.getShort(obj, offset); } - void setFieldS(C obj, short x) { unsafe.putShort(obj, offset, x); } - char getFieldC(C obj) { return unsafe.getChar(obj, offset); } - void setFieldC(C obj, char x) { unsafe.putChar(obj, offset, x); } - @SuppressWarnings("unchecked") - V getFieldL(C obj) { return (V) unsafe.getObject(obj, offset); } - @SuppressWarnings("unchecked") - void setFieldL(C obj, V x) { unsafe.putObject(obj, offset, x); } - // cast (V) is OK here, since we wrap convertArguments around the MH. - - static Integer fieldOffset(final MemberName field) { - return AccessController.doPrivileged(new PrivilegedAction<Integer>() { - public Integer run() { - try { - Class c = field.getDeclaringClass(); - // FIXME: Should not have to create 'f' to get this value. - java.lang.reflect.Field f = c.getDeclaredField(field.getName()); - return unsafe.fieldOffset(f); - } catch (NoSuchFieldException ee) { - throw uncaughtException(ee); - } - } - }); - } - - int getStaticI() { return unsafe.getInt(base, offset); } - void setStaticI(int x) { unsafe.putInt(base, offset, x); } - long getStaticJ() { return unsafe.getLong(base, offset); } - void setStaticJ(long x) { unsafe.putLong(base, offset, x); } - float getStaticF() { return unsafe.getFloat(base, offset); } - void setStaticF(float x) { unsafe.putFloat(base, offset, x); } - double getStaticD() { return unsafe.getDouble(base, offset); } - void setStaticD(double x) { unsafe.putDouble(base, offset, x); } - boolean getStaticZ() { return unsafe.getBoolean(base, offset); } - void setStaticZ(boolean x) { unsafe.putBoolean(base, offset, x); } - byte getStaticB() { return unsafe.getByte(base, offset); } - void setStaticB(byte x) { unsafe.putByte(base, offset, x); } - short getStaticS() { return unsafe.getShort(base, offset); } - void setStaticS(short x) { unsafe.putShort(base, offset, x); } - char getStaticC() { return unsafe.getChar(base, offset); } - void setStaticC(char x) { unsafe.putChar(base, offset, x); } - V getStaticL() { return (V) unsafe.getObject(base, offset); } - void setStaticL(V x) { unsafe.putObject(base, offset, x); } - - static String fname(Class<?> vclass, boolean isSetter, boolean isStatic) { - String stem; - if (!isStatic) - stem = (!isSetter ? "getField" : "setField"); - else - stem = (!isSetter ? "getStatic" : "setStatic"); - return stem + Wrapper.basicTypeChar(vclass); - } - static MethodType ftype(Class<?> cclass, Class<?> vclass, boolean isSetter, boolean isStatic) { - MethodType type; - if (!isStatic) { - if (!isSetter) - return MethodType.methodType(vclass, cclass); - else - return MethodType.methodType(void.class, cclass, vclass); - } else { - if (!isSetter) - return MethodType.methodType(vclass); - else - return MethodType.methodType(void.class, vclass); - } - } - static MethodHandle fhandle(Class<?> cclass, Class<?> vclass, boolean isSetter, boolean isStatic) { - String name = FieldAccessor.fname(vclass, isSetter, isStatic); - if (cclass.isPrimitive()) throw newIllegalArgumentException("primitive "+cclass); - Class<?> ecclass = Object.class; //erase this type - Class<?> evclass = vclass; - if (!evclass.isPrimitive()) evclass = Object.class; - MethodType type = FieldAccessor.ftype(ecclass, evclass, isSetter, isStatic); - MethodHandle mh; - try { - mh = IMPL_LOOKUP.findVirtual(FieldAccessor.class, name, type); - } catch (ReflectiveOperationException ex) { - throw uncaughtException(ex); - } - if (evclass != vclass || (!isStatic && ecclass != cclass)) { - MethodType strongType = FieldAccessor.ftype(cclass, vclass, isSetter, isStatic); - strongType = strongType.insertParameterTypes(0, FieldAccessor.class); - mh = convertArguments(mh, strongType, 0); - } - return mh; - } - - /// Support for array element access - static final HashMap<Class<?>, MethodHandle[]> ARRAY_CACHE = - new HashMap<Class<?>, MethodHandle[]>(); - // FIXME: Cache on the classes themselves, not here. - static boolean doCache(Class<?> elemClass) { - if (elemClass.isPrimitive()) return true; - ClassLoader cl = elemClass.getClassLoader(); - return cl == null || cl == ClassLoader.getSystemClassLoader(); - } - static int getElementI(int[] a, int i) { return a[i]; } - static void setElementI(int[] a, int i, int x) { a[i] = x; } - static long getElementJ(long[] a, int i) { return a[i]; } - static void setElementJ(long[] a, int i, long x) { a[i] = x; } - static float getElementF(float[] a, int i) { return a[i]; } - static void setElementF(float[] a, int i, float x) { a[i] = x; } - static double getElementD(double[] a, int i) { return a[i]; } - static void setElementD(double[] a, int i, double x) { a[i] = x; } - static boolean getElementZ(boolean[] a, int i) { return a[i]; } - static void setElementZ(boolean[] a, int i, boolean x) { a[i] = x; } - static byte getElementB(byte[] a, int i) { return a[i]; } - static void setElementB(byte[] a, int i, byte x) { a[i] = x; } - static short getElementS(short[] a, int i) { return a[i]; } - static void setElementS(short[] a, int i, short x) { a[i] = x; } - static char getElementC(char[] a, int i) { return a[i]; } - static void setElementC(char[] a, int i, char x) { a[i] = x; } - static Object getElementL(Object[] a, int i) { return a[i]; } - static void setElementL(Object[] a, int i, Object x) { a[i] = x; } - static <V> V getElementL(Class<V[]> aclass, V[] a, int i) { return aclass.cast(a)[i]; } - static <V> void setElementL(Class<V[]> aclass, V[] a, int i, V x) { aclass.cast(a)[i] = x; } - - static String aname(Class<?> aclass, boolean isSetter) { - Class<?> vclass = aclass.getComponentType(); - if (vclass == null) throw new IllegalArgumentException(); - return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(vclass); - } - static MethodType atype(Class<?> aclass, boolean isSetter) { - Class<?> vclass = aclass.getComponentType(); - if (!isSetter) - return MethodType.methodType(vclass, aclass, int.class); - else - return MethodType.methodType(void.class, aclass, int.class, vclass); - } - static MethodHandle ahandle(Class<?> aclass, boolean isSetter) { - Class<?> vclass = aclass.getComponentType(); - String name = FieldAccessor.aname(aclass, isSetter); - Class<?> caclass = null; - if (!vclass.isPrimitive() && vclass != Object.class) { - caclass = aclass; - aclass = Object[].class; - vclass = Object.class; - } - MethodType type = FieldAccessor.atype(aclass, isSetter); - if (caclass != null) - type = type.insertParameterTypes(0, Class.class); - MethodHandle mh; - try { - mh = IMPL_LOOKUP.findStatic(FieldAccessor.class, name, type); - } catch (ReflectiveOperationException ex) { - throw uncaughtException(ex); - } - if (caclass != null) { - MethodType strongType = FieldAccessor.atype(caclass, isSetter); - mh = mh.bindTo(caclass); - mh = convertArguments(mh, strongType, 0); - } - return mh; - } - } - - /** Bind a predetermined first argument to the given direct method handle. - * Callable only from MethodHandles. - * @param token Proof that the caller has access to this package. - * @param target Any direct method handle. - * @param receiver Receiver (or first static method argument) to pre-bind. - * @return a BoundMethodHandle for the given DirectMethodHandle, or null if it does not exist - */ - static - MethodHandle bindReceiver(MethodHandle target, Object receiver) { - if (receiver == null) return null; - return new BoundMethodHandle(target, receiver, 0); - } - - /** Bind a predetermined argument to the given arbitrary method handle. - * Callable only from MethodHandles. - * @param token Proof that the caller has access to this package. - * @param target Any method handle. - * @param receiver Argument (which can be a boxed primitive) to pre-bind. - * @return a suitable BoundMethodHandle - */ - static - MethodHandle bindArgument(MethodHandle target, int argnum, Object receiver) { - return new BoundMethodHandle(target, receiver, argnum); - } - - static native MethodHandle permuteArguments(MethodHandle target, - MethodType newType, - MethodType oldType, - int[] permutationOrNull); - - /*non-public*/ static - MethodHandle convertArguments(MethodHandle target, MethodType newType, int level) { - MethodType oldType = target.type(); - if (oldType.equals(newType)) - return target; - assert(level > 1 || oldType.isConvertibleTo(newType)); - MethodHandle retFilter = null; - Class<?> oldRT = oldType.returnType(); - Class<?> newRT = newType.returnType(); - if (!VerifyType.isNullConversion(oldRT, newRT)) { - if (oldRT == void.class) { - Wrapper wrap = newRT.isPrimitive() ? Wrapper.forPrimitiveType(newRT) : Wrapper.OBJECT; - retFilter = ValueConversions.zeroConstantFunction(wrap); - } else { - retFilter = MethodHandles.identity(newRT); - retFilter = convertArguments(retFilter, retFilter.type().changeParameterType(0, oldRT), level); - } - newType = newType.changeReturnType(oldRT); - } - MethodHandle res = null; - Exception ex = null; - try { - res = convertArguments(target, newType, oldType, level); - } catch (IllegalArgumentException ex1) { - ex = ex1; - } - if (res == null) { - WrongMethodTypeException wmt = new WrongMethodTypeException("cannot convert to "+newType+": "+target); - wmt.initCause(ex); - throw wmt; - } - if (retFilter != null) - res = MethodHandles.filterReturnValue(res, retFilter); - return res; - } - - static MethodHandle convertArguments(MethodHandle target, - MethodType newType, - MethodType oldType, - int level) { - assert(oldType.parameterCount() == target.type().parameterCount()); - if (newType == oldType) - return target; - if (oldType.parameterCount() != newType.parameterCount()) - throw newIllegalArgumentException("mismatched parameter count", oldType, newType); - return AdapterMethodHandle.makePairwiseConvert(newType, target, level); - } - - static MethodHandle spreadArguments(MethodHandle target, Class<?> arrayType, int arrayLength) { - MethodType oldType = target.type(); - int nargs = oldType.parameterCount(); - int keepPosArgs = nargs - arrayLength; - MethodType newType = oldType - .dropParameterTypes(keepPosArgs, nargs) - .insertParameterTypes(keepPosArgs, arrayType); - return spreadArguments(target, newType, keepPosArgs, arrayType, arrayLength); - } - // called internally only - static MethodHandle spreadArgumentsFromPos(MethodHandle target, MethodType newType, int spreadArgPos) { - int arrayLength = target.type().parameterCount() - spreadArgPos; - return spreadArguments(target, newType, spreadArgPos, Object[].class, arrayLength); - } - static MethodHandle spreadArguments(MethodHandle target, - MethodType newType, - int spreadArgPos, - Class<?> arrayType, - int arrayLength) { - // TO DO: maybe allow the restarg to be Object and implicitly cast to Object[] - MethodType oldType = target.type(); - // spread the last argument of newType to oldType - assert(arrayLength == oldType.parameterCount() - spreadArgPos); - assert(newType.parameterType(spreadArgPos) == arrayType); - return AdapterMethodHandle.makeSpreadArguments(newType, target, arrayType, spreadArgPos, arrayLength); - } - - static MethodHandle collectArguments(MethodHandle target, - int collectArg, - MethodHandle collector) { - MethodType type = target.type(); - Class<?> collectType = collector.type().returnType(); - assert(collectType != void.class); // else use foldArguments - if (collectType != type.parameterType(collectArg)) - target = target.asType(type.changeParameterType(collectArg, collectType)); - MethodType newType = type - .dropParameterTypes(collectArg, collectArg+1) - .insertParameterTypes(collectArg, collector.type().parameterArray()); - return collectArguments(target, newType, collectArg, collector); - } - static MethodHandle collectArguments(MethodHandle target, - MethodType newType, - int collectArg, - MethodHandle collector) { - MethodType oldType = target.type(); // (a...,c)=>r - // newType // (a..., b...)=>r - MethodType colType = collector.type(); // (b...)=>c - // oldType // (a..., b...)=>r - assert(newType.parameterCount() == collectArg + colType.parameterCount()); - assert(oldType.parameterCount() == collectArg + 1); - return AdapterMethodHandle.makeCollectArguments(target, collector, collectArg, false); - } - - static MethodHandle filterArgument(MethodHandle target, - int pos, - MethodHandle filter) { - MethodType ttype = target.type(); - MethodType ftype = filter.type(); - assert(ftype.parameterCount() == 1); - return AdapterMethodHandle.makeCollectArguments(target, filter, pos, false); - } - - static MethodHandle foldArguments(MethodHandle target, - MethodType newType, - int foldPos, - MethodHandle combiner) { - MethodType oldType = target.type(); - MethodType ctype = combiner.type(); - return AdapterMethodHandle.makeCollectArguments(target, combiner, foldPos, true); - } - - static - MethodHandle dropArguments(MethodHandle target, - MethodType newType, int argnum) { - int drops = newType.parameterCount() - target.type().parameterCount(); - return AdapterMethodHandle.makeDropArguments(newType, target, argnum, drops); - } - - static - MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) { - return testResult ? target : fallback; - } - - static MethodHandle SELECT_ALTERNATIVE; - static MethodHandle selectAlternative() { - if (SELECT_ALTERNATIVE != null) return SELECT_ALTERNATIVE; - try { - SELECT_ALTERNATIVE - = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "selectAlternative", - MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class)); - } catch (ReflectiveOperationException ex) { - throw new RuntimeException(ex); - } - return SELECT_ALTERNATIVE; - } - - static - MethodHandle makeGuardWithTest(MethodHandle test, - MethodHandle target, - MethodHandle fallback) { - // gwt(arg...) - // [fold]=> continueAfterTest(z=test(arg...), arg...) - // [filter]=> (tf=select(z))(arg...) - // where select(z) = select(z, t, f).bindTo(t, f) => z ? t f - // [tailcall]=> tf(arg...) - assert(test.type().returnType() == boolean.class); - MethodType targetType = target.type(); - MethodType foldTargetType = targetType.insertParameterTypes(0, boolean.class); - // working backwards, as usual: - assert(target.type().equals(fallback.type())); - MethodHandle tailcall = MethodHandles.exactInvoker(target.type()); - MethodHandle select = selectAlternative(); - select = bindArgument(select, 2, fallback); - select = bindArgument(select, 1, target); - // select(z: boolean) => (z ? target : fallback) - MethodHandle filter = filterArgument(tailcall, 0, select); - assert(filter.type().parameterType(0) == boolean.class); - MethodHandle fold = foldArguments(filter, filter.type().dropParameterTypes(0, 1), 0, test); - return fold; - } - - private static class GuardWithCatch extends BoundMethodHandle { - private final MethodHandle target; - private final Class<? extends Throwable> exType; - private final MethodHandle catcher; - GuardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) { - this(INVOKES[target.type().parameterCount()], target, exType, catcher); - } - // FIXME: Build the control flow out of foldArguments. - GuardWithCatch(MethodHandle invoker, - MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) { - super(invoker); - this.target = target; - this.exType = exType; - this.catcher = catcher; - } - @Override - String debugString() { - return addTypeString(target, this); - } - private Object invoke_V(Object... av) throws Throwable { - try { - return target.invokeExact(av); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, av); - } - } - private Object invoke_L0() throws Throwable { - try { - return target.invokeExact(); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t); - } - } - private Object invoke_L1(Object a0) throws Throwable { - try { - return target.invokeExact(a0); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0); - } - } - private Object invoke_L2(Object a0, Object a1) throws Throwable { - try { - return target.invokeExact(a0, a1); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1); - } - } - private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { - try { - return target.invokeExact(a0, a1, a2); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1, a2); - } - } - private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { - try { - return target.invokeExact(a0, a1, a2, a3); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1, a2, a3); - } - } - private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { - try { - return target.invokeExact(a0, a1, a2, a3, a4); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1, a2, a3, a4); - } - } - private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { - try { - return target.invokeExact(a0, a1, a2, a3, a4, a5); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5); - } - } - private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { - try { - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6); - } - } - private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { - try { - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6, a7); - } - } - static MethodHandle[] makeInvokes() { - ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>(); - MethodHandles.Lookup lookup = IMPL_LOOKUP; - for (;;) { - int nargs = invokes.size(); - String name = "invoke_L"+nargs; - MethodHandle invoke = null; - try { - invoke = lookup.findVirtual(GuardWithCatch.class, name, MethodType.genericMethodType(nargs)); - } catch (ReflectiveOperationException ex) { - } - if (invoke == null) break; - invokes.add(invoke); - } - assert(invokes.size() == 9); // current number of methods - return invokes.toArray(new MethodHandle[0]); - }; - static final MethodHandle[] INVOKES = makeInvokes(); - // For testing use this: - //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2); - static final MethodHandle VARARGS_INVOKE; - static { - try { - VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true)); - } catch (ReflectiveOperationException ex) { - throw uncaughtException(ex); - } - } - } - - - static - MethodHandle makeGuardWithCatch(MethodHandle target, - Class<? extends Throwable> exType, - MethodHandle catcher) { - MethodType type = target.type(); - MethodType ctype = catcher.type(); - int nargs = type.parameterCount(); - if (nargs < GuardWithCatch.INVOKES.length) { - MethodType gtype = type.generic(); - MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class); - // Note: convertArguments(...2) avoids interface casts present in convertArguments(...0) - MethodHandle gtarget = convertArguments(target, gtype, type, 2); - MethodHandle gcatcher = convertArguments(catcher, gcatchType, ctype, 2); - MethodHandle gguard = new GuardWithCatch(gtarget, exType, gcatcher); - if (gtarget == null || gcatcher == null || gguard == null) return null; - return convertArguments(gguard, type, gtype, 2); - } else { - MethodType gtype = MethodType.genericMethodType(0, true); - MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class); - MethodHandle gtarget = spreadArgumentsFromPos(target, gtype, 0); - catcher = catcher.asType(ctype.changeParameterType(0, Throwable.class)); - MethodHandle gcatcher = spreadArgumentsFromPos(catcher, gcatchType, 1); - MethodHandle gguard = new GuardWithCatch(GuardWithCatch.VARARGS_INVOKE, gtarget, exType, gcatcher); - if (gtarget == null || gcatcher == null || gguard == null) return null; - return collectArguments(gguard, type, 0, ValueConversions.varargsArray(nargs)).asType(type); - } - } - - static - MethodHandle throwException(MethodType type) { - return AdapterMethodHandle.makeRetypeRaw(type, throwException()); - } - - static MethodHandle THROW_EXCEPTION; - static MethodHandle throwException() { - if (THROW_EXCEPTION != null) return THROW_EXCEPTION; - try { - THROW_EXCEPTION - = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException", - MethodType.methodType(Empty.class, Throwable.class)); - } catch (ReflectiveOperationException ex) { - throw new RuntimeException(ex); - } - return THROW_EXCEPTION; - } - static <T extends Throwable> Empty throwException(T t) throws T { throw t; } -} diff --git a/openjdk/java/lang/invoke/MethodHandleNatives.java b/openjdk/java/lang/invoke/MethodHandleNatives.java deleted file mode 100644 index 4f7da894..00000000 --- a/openjdk/java/lang/invoke/MethodHandleNatives.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Extensively modified for IKVM.NET by Jeroen Frijters - * Copyright (C) 2011 Jeroen Frijters - */ - -package java.lang.invoke; - -import java.lang.invoke.MethodHandles.Lookup; -import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Field; -import static java.lang.invoke.MethodHandleNatives.Constants.*; -import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; - -/** - * The JVM interface for the method handles package is all here. - * This is an interface internal and private to an implemetantion of JSR 292. - * <em>This class is not part of the JSR 292 standard.</em> - * @author jrose - */ -class MethodHandleNatives { - - private MethodHandleNatives() { } // static only - - /// MethodName support - - static native void init(MemberName self, Object ref); - static native void expand(MemberName self); - static native void resolve(MemberName self, Class<?> caller); - static native int getMembers(Class<?> defc, String matchName, String matchSig, - int matchFlags, Class<?> caller, int skip, MemberName[] results); - - /** Initialize a method type, once per form. */ - static void init(MethodType self) { } - - /** Fetch the name of the handled method, if available. - * This routine is for debugging and reflection. - */ - static MemberName getMethodName(MethodHandle self) { - throw new ikvm.internal.NotYetImplementedError(); - } - - static Object[] makeTarget(Class<?> defc, String name, String sig, int mods, Class<?> refc) { - return new Object[] { defc, name, sig, mods, refc }; - } - - /** Java copy of MethodHandlePushLimit in range 2..255. */ - static final int JVM_PUSH_LIMIT; - /** JVM stack motion (in words) after one slot is pushed, usually -1. - */ - static final int JVM_STACK_MOVE_UNIT; - - /** Which conv-ops are implemented by the JVM? */ - static final int CONV_OP_IMPLEMENTED_MASK; - /** Derived mode flag. Only false on some old JVM implementations. */ - static final boolean HAVE_RICOCHET_FRAMES; - - static final int OP_ROT_ARGS_DOWN_LIMIT_BIAS; - - static { - int k; - JVM_PUSH_LIMIT = 3; - JVM_STACK_MOVE_UNIT = 1; - k = 0; - CONV_OP_IMPLEMENTED_MASK = (k != 0) ? k : DEFAULT_CONV_OP_IMPLEMENTED_MASK; - k = 0; - OP_ROT_ARGS_DOWN_LIMIT_BIAS = (k != 0) ? (byte)k : -1; - HAVE_RICOCHET_FRAMES = (CONV_OP_IMPLEMENTED_MASK & (1<<OP_COLLECT_ARGS)) != 0; - //sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init"); - } - - // All compile-time constants go here. - // There is an opportunity to check them against the JVM's idea of them. - static class Constants { - Constants() { } // static only - // MethodHandleImpl - static final int // for getConstant - GC_JVM_PUSH_LIMIT = 0, - GC_JVM_STACK_MOVE_UNIT = 1, - GC_CONV_OP_IMPLEMENTED_MASK = 2, - GC_OP_ROT_ARGS_DOWN_LIMIT_BIAS = 3; - static final int - ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method) - ETF_DIRECT_HANDLE = 1, // ultimate method handle (will be a DMH, may be self) - ETF_METHOD_NAME = 2, // ultimate method as MemberName - ETF_REFLECT_METHOD = 3; // ultimate method as java.lang.reflect object (sans refClass) - - // MemberName - // The JVM uses values of -2 and above for vtable indexes. - // Field values are simple positive offsets. - // Ref: src/share/vm/oops/methodOop.hpp - // This value is negative enough to avoid such numbers, - // but not too negative. - static final int - MN_IS_METHOD = 0x00010000, // method (not constructor) - MN_IS_CONSTRUCTOR = 0x00020000, // constructor - MN_IS_FIELD = 0x00040000, // field - MN_IS_TYPE = 0x00080000, // nested type - MN_SEARCH_SUPERCLASSES = 0x00100000, // for MHN.getMembers - MN_SEARCH_INTERFACES = 0x00200000, // for MHN.getMembers - VM_INDEX_UNINITIALIZED = -99; - - // BoundMethodHandle - /** Constants for decoding the vmargslot field, which contains 2 values. */ - static final int - ARG_SLOT_PUSH_SHIFT = 16, - ARG_SLOT_MASK = (1<<ARG_SLOT_PUSH_SHIFT)-1; - - // AdapterMethodHandle - /** Conversions recognized by the JVM. - * They must align with the constants in java.lang.invoke.AdapterMethodHandle, - * in the JVM file hotspot/src/share/vm/classfile/javaClasses.hpp. - */ - static final int - OP_RETYPE_ONLY = 0x0, // no argument changes; straight retype - OP_RETYPE_RAW = 0x1, // straight retype, trusted (void->int, Object->T) - OP_CHECK_CAST = 0x2, // ref-to-ref conversion; requires a Class argument - OP_PRIM_TO_PRIM = 0x3, // converts from one primitive to another - OP_REF_TO_PRIM = 0x4, // unboxes a wrapper to produce a primitive - OP_PRIM_TO_REF = 0x5, // boxes a primitive into a wrapper - OP_SWAP_ARGS = 0x6, // swap arguments (vminfo is 2nd arg) - OP_ROT_ARGS = 0x7, // rotate arguments (vminfo is displaced arg) - OP_DUP_ARGS = 0x8, // duplicates one or more arguments (at TOS) - OP_DROP_ARGS = 0x9, // remove one or more argument slots - OP_COLLECT_ARGS = 0xA, // combine arguments using an auxiliary function - OP_SPREAD_ARGS = 0xB, // expand in place a varargs array (of known size) - OP_FOLD_ARGS = 0xC, // combine but do not remove arguments; prepend result - //OP_UNUSED_13 = 0xD, // unused code, perhaps for reified argument lists - CONV_OP_LIMIT = 0xE; // limit of CONV_OP enumeration - /** Shift and mask values for decoding the AMH.conversion field. - * These numbers are shared with the JVM for creating AMHs. - */ - static final int - CONV_OP_MASK = 0xF00, // this nybble contains the conversion op field - CONV_TYPE_MASK = 0x0F, // fits T_ADDRESS and below - CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use - CONV_VMINFO_SHIFT = 0, // position of bits in CONV_VMINFO_MASK - CONV_OP_SHIFT = 8, // position of bits in CONV_OP_MASK - CONV_DEST_TYPE_SHIFT = 12, // byte 2 has the adapter BasicType (if needed) - CONV_SRC_TYPE_SHIFT = 16, // byte 2 has the source BasicType (if needed) - CONV_STACK_MOVE_SHIFT = 20, // high 12 bits give signed SP change - CONV_STACK_MOVE_MASK = (1 << (32 - CONV_STACK_MOVE_SHIFT)) - 1; - - /** Which conv-ops are implemented by the JVM? */ - static final int DEFAULT_CONV_OP_IMPLEMENTED_MASK = - // Value to use if the corresponding JVM query fails. - ((1<<OP_RETYPE_ONLY) - |(1<<OP_RETYPE_RAW) - |(1<<OP_CHECK_CAST) - |(1<<OP_PRIM_TO_PRIM) - |(1<<OP_REF_TO_PRIM) - |(1<<OP_SWAP_ARGS) - |(1<<OP_ROT_ARGS) - |(1<<OP_DUP_ARGS) - |(1<<OP_DROP_ARGS) - //|(1<<OP_SPREAD_ARGS) - ); - - /** - * Basic types as encoded in the JVM. These code values are not - * intended for use outside this class. They are used as part of - * a private interface between the JVM and this class. - */ - static final int - T_BOOLEAN = 4, - T_CHAR = 5, - T_FLOAT = 6, - T_DOUBLE = 7, - T_BYTE = 8, - T_SHORT = 9, - T_INT = 10, - T_LONG = 11, - T_OBJECT = 12, - //T_ARRAY = 13 - T_VOID = 14, - //T_ADDRESS = 15 - T_ILLEGAL = 99; - - /** - * Constant pool reference-kind codes, as used by CONSTANT_MethodHandle CP entries. - */ - static final int - REF_getField = 1, - REF_getStatic = 2, - REF_putField = 3, - REF_putStatic = 4, - REF_invokeVirtual = 5, - REF_invokeStatic = 6, - REF_invokeSpecial = 7, - REF_newInvokeSpecial = 8, - REF_invokeInterface = 9; - } - - /** - * This assertion marks code which was written before ricochet frames were implemented. - * Such code will go away when the ports catch up. - */ - static boolean workaroundWithoutRicochetFrames() { - assert(!HAVE_RICOCHET_FRAMES) : "this code should not be executed if `-XX:+UseRicochetFrames is enabled"; - return true; - } -} diff --git a/openjdk/java/lang/invoke/MethodHandles.java b/openjdk/java/lang/invoke/MethodHandles.java deleted file mode 100644 index 6f0db408..00000000 --- a/openjdk/java/lang/invoke/MethodHandles.java +++ /dev/null @@ -1,2273 +0,0 @@ -/* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang.invoke; - -import java.lang.reflect.*; -import sun.invoke.WrapperInstance; -import sun.invoke.util.ValueConversions; -import sun.invoke.util.VerifyAccess; -import sun.invoke.util.Wrapper; -import java.util.List; -import java.util.ArrayList; -import java.util.Arrays; -import sun.reflect.CallerSensitive; -import sun.reflect.Reflection; -import static java.lang.invoke.MethodHandleStatics.*; -import static java.lang.invoke.MethodHandleNatives.Constants.*; - -/** - * This class consists exclusively of static methods that operate on or return - * method handles. They fall into several categories: - * <ul> - * <li>Lookup methods which help create method handles for methods and fields. - * <li>Combinator methods, which combine or transform pre-existing method handles into new ones. - * <li>Other factory methods to create method handles that emulate other common JVM operations or control flow patterns. - * <li>Wrapper methods which can convert between method handles and interface types. - * </ul> - * <p> - * @author John Rose, JSR 292 EG - */ -public class MethodHandles { - - private MethodHandles() { } // do not instantiate - - private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(); - static { MethodHandleImpl.initStatics(); } - // See IMPL_LOOKUP below. - - //// Method handle creation from ordinary methods. - - /** - * Returns a {@link Lookup lookup object} on the caller, - * which has the capability to access any method handle that the caller has access to, - * including direct method handles to private fields and methods. - * This lookup object is a <em>capability</em> which may be delegated to trusted agents. - * Do not store it in place where untrusted code can access it. - */ - @CallerSensitive - public static Lookup lookup() { - return new Lookup(Reflection.getCallerClass()); - } - - /** - * Returns a {@link Lookup lookup object} which is trusted minimally. - * It can only be used to create method handles to - * publicly accessible fields and methods. - * <p> - * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class} - * of this lookup object will be {@link java.lang.Object}. - * <p> - * The lookup class can be changed to any other class {@code C} using an expression of the form - * {@linkplain Lookup#in <code>publicLookup().in(C.class)</code>}. - * Since all classes have equal access to public names, - * such a change would confer no new access rights. - */ - public static Lookup publicLookup() { - return Lookup.PUBLIC_LOOKUP; - } - - /** - * A <em>lookup object</em> is a factory for creating method handles, - * when the creation requires access checking. - * Method handles do not perform - * access checks when they are called, but rather when they are created. - * Therefore, method handle access - * restrictions must be enforced when a method handle is created. - * The caller class against which those restrictions are enforced - * is known as the {@linkplain #lookupClass lookup class}. - * <p> - * A lookup class which needs to create method handles will call - * {@link MethodHandles#lookup MethodHandles.lookup} to create a factory for itself. - * When the {@code Lookup} factory object is created, the identity of the lookup class is - * determined, and securely stored in the {@code Lookup} object. - * The lookup class (or its delegates) may then use factory methods - * on the {@code Lookup} object to create method handles for access-checked members. - * This includes all methods, constructors, and fields which are allowed to the lookup class, - * even private ones. - * <p> - * The factory methods on a {@code Lookup} object correspond to all major - * use cases for methods, constructors, and fields. - * Here is a summary of the correspondence between these factory methods and - * the behavior the resulting method handles: - * <code> - * <table border=1 cellpadding=5 summary="lookup method behaviors"> - * <tr><th>lookup expression</th><th>member</th><th>behavior</th></tr> - * <tr> - * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td> - * <td>FT f;</td><td>(T) this.f;</td> - * </tr> - * <tr> - * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</td> - * <td>static<br>FT f;</td><td>(T) C.f;</td> - * </tr> - * <tr> - * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</td> - * <td>FT f;</td><td>this.f = x;</td> - * </tr> - * <tr> - * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}</td> - * <td>static<br>FT f;</td><td>C.f = arg;</td> - * </tr> - * <tr> - * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}</td> - * <td>T m(A*);</td><td>(T) this.m(arg*);</td> - * </tr> - * <tr> - * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}</td> - * <td>static<br>T m(A*);</td><td>(T) C.m(arg*);</td> - * </tr> - * <tr> - * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}</td> - * <td>T m(A*);</td><td>(T) super.m(arg*);</td> - * </tr> - * <tr> - * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}</td> - * <td>C(A*);</td><td>(T) new C(arg*);</td> - * </tr> - * <tr> - * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}</td> - * <td>(static)?<br>FT f;</td><td>(FT) aField.get(thisOrNull);</td> - * </tr> - * <tr> - * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}</td> - * <td>(static)?<br>FT f;</td><td>aField.set(thisOrNull, arg);</td> - * </tr> - * <tr> - * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td> - * <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td> - * </tr> - * <tr> - * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}</td> - * <td>C(A*);</td><td>(C) aConstructor.newInstance(arg*);</td> - * </tr> - * <tr> - * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td> - * <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td> - * </tr> - * </table> - * </code> - * Here, the type {@code C} is the class or interface being searched for a member, - * documented as a parameter named {@code refc} in the lookup methods. - * The method or constructor type {@code MT} is composed from the return type {@code T} - * and the sequence of argument types {@code A*}. - * Both {@code MT} and the field type {@code FT} are documented as a parameter named {@code type}. - * The formal parameter {@code this} stands for the self-reference of type {@code C}; - * if it is present, it is always the leading argument to the method handle invocation. - * The name {@code arg} stands for all the other method handle arguments. - * In the code examples for the Core Reflection API, the name {@code thisOrNull} - * stands for a null reference if the accessed method or field is static, - * and {@code this} otherwise. - * The names {@code aMethod}, {@code aField}, and {@code aConstructor} stand - * for reflective objects corresponding to the given members. - * <p> - * In cases where the given member is of variable arity (i.e., a method or constructor) - * the returned method handle will also be of {@linkplain MethodHandle#asVarargsCollector variable arity}. - * In all other cases, the returned method handle will be of fixed arity. - * <p> - * The equivalence between looked-up method handles and underlying - * class members can break down in a few ways: - * <ul> - * <li>If {@code C} is not symbolically accessible from the lookup class's loader, - * the lookup can still succeed, even when there is no equivalent - * Java expression or bytecoded constant. - * <li>Likewise, if {@code T} or {@code MT} - * is not symbolically accessible from the lookup class's loader, - * the lookup can still succeed. - * For example, lookups for {@code MethodHandle.invokeExact} and - * {@code MethodHandle.invoke} will always succeed, regardless of requested type. - * <li>If there is a security manager installed, it can forbid the lookup - * on various grounds (<a href="#secmgr">see below</a>). - * By contrast, the {@code ldc} instruction is not subject to - * security manager checks. - * </ul> - * - * <h3><a name="access"></a>Access checking</h3> - * Access checks are applied in the factory methods of {@code Lookup}, - * when a method handle is created. - * This is a key difference from the Core Reflection API, since - * {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke} - * performs access checking against every caller, on every call. - * <p> - * All access checks start from a {@code Lookup} object, which - * compares its recorded lookup class against all requests to - * create method handles. - * A single {@code Lookup} object can be used to create any number - * of access-checked method handles, all checked against a single - * lookup class. - * <p> - * A {@code Lookup} object can be shared with other trusted code, - * such as a metaobject protocol. - * A shared {@code Lookup} object delegates the capability - * to create method handles on private members of the lookup class. - * Even if privileged code uses the {@code Lookup} object, - * the access checking is confined to the privileges of the - * original lookup class. - * <p> - * A lookup can fail, because - * the containing class is not accessible to the lookup class, or - * because the desired class member is missing, or because the - * desired class member is not accessible to the lookup class. - * In any of these cases, a {@code ReflectiveOperationException} will be - * thrown from the attempted lookup. The exact class will be one of - * the following: - * <ul> - * <li>NoSuchMethodException — if a method is requested but does not exist - * <li>NoSuchFieldException — if a field is requested but does not exist - * <li>IllegalAccessException — if the member exists but an access check fails - * </ul> - * <p> - * In general, the conditions under which a method handle may be - * looked up for a method {@code M} are exactly equivalent to the conditions - * under which the lookup class could have compiled and resolved a call to {@code M}. - * And the effect of invoking the method handle resulting from the lookup - * is exactly equivalent to executing the compiled and resolved call to {@code M}. - * The same point is true of fields and constructors. - * <p> - * In some cases, access between nested classes is obtained by the Java compiler by creating - * an wrapper method to access a private method of another class - * in the same top-level declaration. - * For example, a nested class {@code C.D} - * can access private members within other related classes such as - * {@code C}, {@code C.D.E}, or {@code C.B}, - * but the Java compiler may need to generate wrapper methods in - * those related classes. In such cases, a {@code Lookup} object on - * {@code C.E} would be unable to those private members. - * A workaround for this limitation is the {@link Lookup#in Lookup.in} method, - * which can transform a lookup on {@code C.E} into one on any of those other - * classes, without special elevation of privilege. - * <p> - * Although bytecode instructions can only refer to classes in - * a related class loader, this API can search for methods in any - * class, as long as a reference to its {@code Class} object is - * available. Such cross-loader references are also possible with the - * Core Reflection API, and are impossible to bytecode instructions - * such as {@code invokestatic} or {@code getfield}. - * There is a {@linkplain java.lang.SecurityManager security manager API} - * to allow applications to check such cross-loader references. - * These checks apply to both the {@code MethodHandles.Lookup} API - * and the Core Reflection API - * (as found on {@link java.lang.Class Class}). - * <p> - * Access checks only apply to named and reflected methods, - * constructors, and fields. - * Other method handle creation methods, such as - * {@link MethodHandle#asType MethodHandle.asType}, - * do not require any access checks, and are done - * with static methods of {@link MethodHandles}, - * independently of any {@code Lookup} object. - * - * <h3>Security manager interactions</h3> - * <a name="secmgr"></a> - * If a security manager is present, member lookups are subject to - * additional checks. - * From one to four calls are made to the security manager. - * Any of these calls can refuse access by throwing a - * {@link java.lang.SecurityException SecurityException}. - * Define {@code smgr} as the security manager, - * {@code refc} as the containing class in which the member - * is being sought, and {@code defc} as the class in which the - * member is actually defined. - * The calls are made according to the following rules: - * <ul> - * <li>In all cases, {@link SecurityManager#checkMemberAccess - * smgr.checkMemberAccess(refc, Member.PUBLIC)} is called. - * <li>If the class loader of the lookup class is not - * the same as or an ancestor of the class loader of {@code refc}, - * then {@link SecurityManager#checkPackageAccess - * smgr.checkPackageAccess(refcPkg)} is called, - * where {@code refcPkg} is the package of {@code refc}. - * <li>If the retrieved member is not public, - * {@link SecurityManager#checkMemberAccess - * smgr.checkMemberAccess(defc, Member.DECLARED)} is called. - * (Note that {@code defc} might be the same as {@code refc}.) - * The default implementation of this security manager method - * inspects the stack to determine the original caller of - * the reflective request (such as {@code findStatic}), - * and performs additional permission checks if the - * class loader of {@code defc} differs from the class - * loader of the class from which the reflective request came. - * <li>If the retrieved member is not public, - * and if {@code defc} and {@code refc} are in different class loaders, - * and if the class loader of the lookup class is not - * the same as or an ancestor of the class loader of {@code defc}, - * then {@link SecurityManager#checkPackageAccess - * smgr.checkPackageAccess(defcPkg)} is called, - * where {@code defcPkg} is the package of {@code defc}. - * </ul> - */ - public static final - class Lookup { - /** The class on behalf of whom the lookup is being performed. */ - private final Class<?> lookupClass; - - /** The allowed sorts of members which may be looked up (PUBLIC, etc.). */ - private final int allowedModes; - - // [IKVM] when dynamically linking method handle constants, we don't want a security manager check - private final boolean noSecurityCheck; - - /** A single-bit mask representing {@code public} access, - * which may contribute to the result of {@link #lookupModes lookupModes}. - * The value, {@code 0x01}, happens to be the same as the value of the - * {@code public} {@linkplain java.lang.reflect.Modifier#PUBLIC modifier bit}. - */ - public static final int PUBLIC = Modifier.PUBLIC; - - /** A single-bit mask representing {@code private} access, - * which may contribute to the result of {@link #lookupModes lookupModes}. - * The value, {@code 0x02}, happens to be the same as the value of the - * {@code private} {@linkplain java.lang.reflect.Modifier#PRIVATE modifier bit}. - */ - public static final int PRIVATE = Modifier.PRIVATE; - - /** A single-bit mask representing {@code protected} access, - * which may contribute to the result of {@link #lookupModes lookupModes}. - * The value, {@code 0x04}, happens to be the same as the value of the - * {@code protected} {@linkplain java.lang.reflect.Modifier#PROTECTED modifier bit}. - */ - public static final int PROTECTED = Modifier.PROTECTED; - - /** A single-bit mask representing {@code package} access (default access), - * which may contribute to the result of {@link #lookupModes lookupModes}. - * The value is {@code 0x08}, which does not correspond meaningfully to - * any particular {@linkplain java.lang.reflect.Modifier modifier bit}. - */ - public static final int PACKAGE = Modifier.STATIC; - - private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE); - private static final int TRUSTED = -1; - - private static int fixmods(int mods) { - mods &= (ALL_MODES - PACKAGE); - return (mods != 0) ? mods : PACKAGE; - } - - /** Tells which class is performing the lookup. It is this class against - * which checks are performed for visibility and access permissions. - * <p> - * The class implies a maximum level of access permission, - * but the permissions may be additionally limited by the bitmask - * {@link #lookupModes lookupModes}, which controls whether non-public members - * can be accessed. - */ - public Class<?> lookupClass() { - return lookupClass; - } - - // This is just for calling out to MethodHandleImpl. - private Class<?> lookupClassOrNull() { - return (allowedModes == TRUSTED) ? null : lookupClass; - } - - /** Tells which access-protection classes of members this lookup object can produce. - * The result is a bit-mask of the bits - * {@linkplain #PUBLIC PUBLIC (0x01)}, - * {@linkplain #PRIVATE PRIVATE (0x02)}, - * {@linkplain #PROTECTED PROTECTED (0x04)}, - * and {@linkplain #PACKAGE PACKAGE (0x08)}. - * <p> - * A freshly-created lookup object - * on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class} - * has all possible bits set, since the caller class can access all its own members. - * A lookup object on a new lookup class - * {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object} - * may have some mode bits set to zero. - * The purpose of this is to restrict access via the new lookup object, - * so that it can access only names which can be reached by the original - * lookup object, and also by the new lookup class. - */ - public int lookupModes() { - return allowedModes & ALL_MODES; - } - - /** Embody the current class (the lookupClass) as a lookup class - * for method handle creation. - * Must be called by from a method in this package, - * which in turn is called by a method not in this package. - * <p> - * Also, don't make it private, lest javac interpose - * an access$N method. - */ - Lookup(Class<?> lookupClass) { - this(lookupClass, ALL_MODES); - checkUnprivilegedlookupClass(lookupClass); - } - - private Lookup(Class<?> lookupClass, int allowedModes) { - this(lookupClass, allowedModes, false); - } - - Lookup(Class<?> lookupClass, int allowedModes, boolean noSecurityCheck) { - this.lookupClass = lookupClass; - this.allowedModes = allowedModes; - this.noSecurityCheck = noSecurityCheck; - } - - /** - * Creates a lookup on the specified new lookup class. - * The resulting object will report the specified - * class as its own {@link #lookupClass lookupClass}. - * <p> - * However, the resulting {@code Lookup} object is guaranteed - * to have no more access capabilities than the original. - * In particular, access capabilities can be lost as follows:<ul> - * <li>If the new lookup class differs from the old one, - * protected members will not be accessible by virtue of inheritance. - * (Protected members may continue to be accessible because of package sharing.) - * <li>If the new lookup class is in a different package - * than the old one, protected and default (package) members will not be accessible. - * <li>If the new lookup class is not within the same package member - * as the old one, private members will not be accessible. - * <li>If the new lookup class is not accessible to the old lookup class, - * then no members, not even public members, will be accessible. - * (In all other cases, public members will continue to be accessible.) - * </ul> - * - * @param requestedLookupClass the desired lookup class for the new lookup object - * @return a lookup object which reports the desired lookup class - * @throws NullPointerException if the argument is null - */ - public Lookup in(Class<?> requestedLookupClass) { - requestedLookupClass.getClass(); // null check - if (allowedModes == TRUSTED) // IMPL_LOOKUP can make any lookup at all - return new Lookup(requestedLookupClass, ALL_MODES); - if (requestedLookupClass == this.lookupClass) - return this; // keep same capabilities - int newModes = (allowedModes & (ALL_MODES & ~PROTECTED)); - if ((newModes & PACKAGE) != 0 - && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) { - newModes &= ~(PACKAGE|PRIVATE); - } - // Allow nestmate lookups to be created without special privilege: - if ((newModes & PRIVATE) != 0 - && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) { - newModes &= ~PRIVATE; - } - if ((newModes & PUBLIC) != 0 - && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass, allowedModes)) { - // The requested class it not accessible from the lookup class. - // No permissions. - newModes = 0; - } - checkUnprivilegedlookupClass(requestedLookupClass); - return new Lookup(requestedLookupClass, newModes); - } - - // Make sure outer class is initialized first. - static { IMPL_NAMES.getClass(); } - - /** Version of lookup which is trusted minimally. - * It can only be used to create method handles to - * publicly accessible members. - */ - static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, PUBLIC); - - /** Package-private version of lookup which is trusted. */ - static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED); - - private static void checkUnprivilegedlookupClass(Class<?> lookupClass) { - String name = lookupClass.getName(); - if (name.startsWith("java.lang.invoke.")) - throw newIllegalArgumentException("illegal lookupClass: "+lookupClass); - } - - /** - * Displays the name of the class from which lookups are to be made. - * (The name is the one reported by {@link java.lang.Class#getName() Class.getName}.) - * If there are restrictions on the access permitted to this lookup, - * this is indicated by adding a suffix to the class name, consisting - * of a slash and a keyword. The keyword represents the strongest - * allowed access, and is chosen as follows: - * <ul> - * <li>If no access is allowed, the suffix is "/noaccess". - * <li>If only public access is allowed, the suffix is "/public". - * <li>If only public and package access are allowed, the suffix is "/package". - * <li>If only public, package, and private access are allowed, the suffix is "/private". - * </ul> - * If none of the above cases apply, it is the case that full - * access (public, package, private, and protected) is allowed. - * In this case, no suffix is added. - * This is true only of an object obtained originally from - * {@link java.lang.invoke.MethodHandles#lookup MethodHandles.lookup}. - * Objects created by {@link java.lang.invoke.MethodHandles.Lookup#in Lookup.in} - * always have restricted access, and will display a suffix. - * <p> - * (It may seem strange that protected access should be - * stronger than private access. Viewed independently from - * package access, protected access is the first to be lost, - * because it requires a direct subclass relationship between - * caller and callee.) - * @see #in - */ - @Override - public String toString() { - String cname = lookupClass.getName(); - switch (allowedModes) { - case 0: // no privileges - return cname + "/noaccess"; - case PUBLIC: - return cname + "/public"; - case PUBLIC|PACKAGE: - return cname + "/package"; - case ALL_MODES & ~PROTECTED: - return cname + "/private"; - case ALL_MODES: - return cname; - case TRUSTED: - return "/trusted"; // internal only; not exported - default: // Should not happen, but it's a bitfield... - cname = cname + "/" + Integer.toHexString(allowedModes); - assert(false) : cname; - return cname; - } - } - - /* Obtain the external caller class, when called from Lookup.<init> or a first-level subroutine. */ - private static Class<?> getCallerClassAtEntryPoint(boolean inSubroutine) { - final int CALLER_DEPTH = 4; - // Stack for the constructor entry point (inSubroutine=false): - // 0: Reflection.getCC, 1: getCallerClassAtEntryPoint, - // 2: Lookup.<init>, 3: MethodHandles.*, 4: caller - // The stack is slightly different for a subroutine of a Lookup.find* method: - // 2: Lookup.*, 3: Lookup.find*.*, 4: caller - // Note: This should be the only use of getCallerClass in this file. - assert(Reflection.getCallerClass(CALLER_DEPTH-2) == Lookup.class); - assert(Reflection.getCallerClass(CALLER_DEPTH-1) == (inSubroutine ? Lookup.class : MethodHandles.class)); - return Reflection.getCallerClass(CALLER_DEPTH); - } - - /** - * Produces a method handle for a static method. - * The type of the method handle will be that of the method. - * (Since static methods do not take receivers, there is no - * additional receiver argument inserted into the method handle type, - * as there would be with {@link #findVirtual findVirtual} or {@link #findSpecial findSpecial}.) - * The method and all its argument types must be accessible to the lookup class. - * If the method's class has not yet been initialized, that is done - * immediately, before the method handle is returned. - * <p> - * The returned method handle will have - * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if - * the method's variable arity modifier bit ({@code 0x0080}) is set. - * @param refc the class from which the method is accessed - * @param name the name of the method - * @param type the type of the method - * @return the desired method handle - * @throws NoSuchMethodException if the method does not exist - * @throws IllegalAccessException if access checking fails, - * or if the method is not {@code static}, - * or if the method's variable arity modifier bit - * is set and {@code asVarargsCollector} fails - * @exception SecurityException if a security manager is present and it - * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> - * @throws NullPointerException if any argument is null - */ - public - MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { - MemberName method = resolveOrFail(refc, name, type, true); - checkSecurityManager(refc, method); // stack walk magic: do not refactor - return accessStatic(refc, method); - } - private - MethodHandle accessStatic(Class<?> refc, MemberName method) throws IllegalAccessException { - checkMethod(refc, method, true); - return MethodHandleImpl.findMethod(method, false, lookupClassOrNull()); - } - private - MethodHandle resolveStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { - MemberName method = resolveOrFail(refc, name, type, true); - return accessStatic(refc, method); - } - - /** - * Produces a method handle for a virtual method. - * The type of the method handle will be that of the method, - * with the receiver type (usually {@code refc}) prepended. - * The method and all its argument types must be accessible to the lookup class. - * <p> - * When called, the handle will treat the first argument as a receiver - * and dispatch on the receiver's type to determine which method - * implementation to enter. - * (The dispatching action is identical with that performed by an - * {@code invokevirtual} or {@code invokeinterface} instruction.) - * <p> - * The returned method handle will have - * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if - * the method's variable arity modifier bit ({@code 0x0080}) is set. - * <p> - * Because of the general equivalence between {@code invokevirtual} - * instructions and method handles produced by {@code findVirtual}, - * if the class is {@code MethodHandle} and the name string is - * {@code invokeExact} or {@code invoke}, the resulting - * method handle is equivalent to one produced by - * {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or - * {@link java.lang.invoke.MethodHandles#invoker MethodHandles.invoker} - * with the same {@code type} argument. - * - * @param refc the class or interface from which the method is accessed - * @param name the name of the method - * @param type the type of the method, with the receiver argument omitted - * @return the desired method handle - * @throws NoSuchMethodException if the method does not exist - * @throws IllegalAccessException if access checking fails, - * or if the method is {@code static} - * or if the method's variable arity modifier bit - * is set and {@code asVarargsCollector} fails - * @exception SecurityException if a security manager is present and it - * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> - * @throws NullPointerException if any argument is null - */ - public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { - MemberName method = resolveOrFail(refc, name, type, false); - checkSecurityManager(refc, method); // stack walk magic: do not refactor - return accessVirtual(refc, method); - } - private MethodHandle resolveVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { - MemberName method = resolveOrFail(refc, name, type, false); - return accessVirtual(refc, method); - } - private MethodHandle accessVirtual(Class<?> refc, MemberName method) throws IllegalAccessException { - checkMethod(refc, method, false); - MethodHandle mh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull()); - return restrictProtectedReceiver(method, mh); - } - - /** - * Produces a method handle which creates an object and initializes it, using - * the constructor of the specified type. - * The parameter types of the method handle will be those of the constructor, - * while the return type will be a reference to the constructor's class. - * The constructor and all its argument types must be accessible to the lookup class. - * If the constructor's class has not yet been initialized, that is done - * immediately, before the method handle is returned. - * <p> - * Note: The requested type must have a return type of {@code void}. - * This is consistent with the JVM's treatment of constructor type descriptors. - * <p> - * The returned method handle will have - * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if - * the constructor's variable arity modifier bit ({@code 0x0080}) is set. - * @param refc the class or interface from which the method is accessed - * @param type the type of the method, with the receiver argument omitted, and a void return type - * @return the desired method handle - * @throws NoSuchMethodException if the constructor does not exist - * @throws IllegalAccessException if access checking fails - * or if the method's variable arity modifier bit - * is set and {@code asVarargsCollector} fails - * @exception SecurityException if a security manager is present and it - * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> - * @throws NullPointerException if any argument is null - */ - public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException { - String name = "<init>"; - MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull()); - checkSecurityManager(refc, ctor); // stack walk magic: do not refactor - return accessConstructor(refc, ctor); - } - private MethodHandle accessConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException { - assert(ctor.isConstructor()); - checkAccess(refc, ctor); - MethodHandle rawMH = MethodHandleImpl.findMethod(ctor, false, lookupClassOrNull()); - MethodHandle allocMH = MethodHandleImpl.makeAllocator(rawMH); - return fixVarargs(allocMH, rawMH); - } - private MethodHandle resolveConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException { - String name = "<init>"; - MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull()); - return accessConstructor(refc, ctor); - } - - /** Return a version of MH which matches matchMH w.r.t. isVarargsCollector. */ - private static MethodHandle fixVarargs(MethodHandle mh, MethodHandle matchMH) { - boolean va1 = mh.isVarargsCollector(); - boolean va2 = matchMH.isVarargsCollector(); - if (va1 == va2) { - return mh; - } else if (va2) { - MethodType type = mh.type(); - int arity = type.parameterCount(); - return mh.asVarargsCollector(type.parameterType(arity-1)); - } else { - return mh.asFixedArity(); - } - } - - /** - * Produces an early-bound method handle for a virtual method, - * as if called from an {@code invokespecial} - * instruction from {@code caller}. - * The type of the method handle will be that of the method, - * with a suitably restricted receiver type (such as {@code caller}) prepended. - * The method and all its argument types must be accessible - * to the caller. - * <p> - * When called, the handle will treat the first argument as a receiver, - * but will not dispatch on the receiver's type. - * (This direct invocation action is identical with that performed by an - * {@code invokespecial} instruction.) - * <p> - * If the explicitly specified caller class is not identical with the - * lookup class, or if this lookup object does not have private access - * privileges, the access fails. - * <p> - * The returned method handle will have - * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if - * the method's variable arity modifier bit ({@code 0x0080}) is set. - * @param refc the class or interface from which the method is accessed - * @param name the name of the method (which must not be "<init>") - * @param type the type of the method, with the receiver argument omitted - * @param specialCaller the proposed calling class to perform the {@code invokespecial} - * @return the desired method handle - * @throws NoSuchMethodException if the method does not exist - * @throws IllegalAccessException if access checking fails - * or if the method's variable arity modifier bit - * is set and {@code asVarargsCollector} fails - * @exception SecurityException if a security manager is present and it - * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> - * @throws NullPointerException if any argument is null - */ - public MethodHandle findSpecial(Class<?> refc, String name, MethodType type, - Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException { - checkSpecialCaller(specialCaller); - MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller); - checkSecurityManager(refc, method); // stack walk magic: do not refactor - return accessSpecial(refc, method, specialCaller); - } - private MethodHandle accessSpecial(Class<?> refc, MemberName method, - Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException { - checkMethod(refc, method, false); - MethodHandle mh = MethodHandleImpl.findMethod(method, false, specialCaller); - return restrictReceiver(method, mh, specialCaller); - } - private MethodHandle resolveSpecial(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { - Class<?> specialCaller = lookupClass(); - checkSpecialCaller(specialCaller); - MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller); - return accessSpecial(refc, method, specialCaller); - } - - /** - * Produces a method handle giving read access to a non-static field. - * The type of the method handle will have a return type of the field's - * value type. - * The method handle's single argument will be the instance containing - * the field. - * Access checking is performed immediately on behalf of the lookup class. - * @param refc the class or interface from which the method is accessed - * @param name the field's name - * @param type the field's type - * @return a method handle which can load values from the field - * @throws NoSuchFieldException if the field does not exist - * @throws IllegalAccessException if access checking fails, or if the field is {@code static} - * @exception SecurityException if a security manager is present and it - * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> - * @throws NullPointerException if any argument is null - */ - public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { - MemberName field = resolveOrFail(refc, name, type, false); - checkSecurityManager(refc, field); // stack walk magic: do not refactor - return makeAccessor(refc, field, false, false, 0); - } - private MethodHandle resolveGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { - MemberName field = resolveOrFail(refc, name, type, false); - return makeAccessor(refc, field, false, false, 0); - } - - /** - * Produces a method handle giving write access to a non-static field. - * The type of the method handle will have a void return type. - * The method handle will take two arguments, the instance containing - * the field, and the value to be stored. - * The second argument will be of the field's value type. - * Access checking is performed immediately on behalf of the lookup class. - * @param refc the class or interface from which the method is accessed - * @param name the field's name - * @param type the field's type - * @return a method handle which can store values into the field - * @throws NoSuchFieldException if the field does not exist - * @throws IllegalAccessException if access checking fails, or if the field is {@code static} - * @exception SecurityException if a security manager is present and it - * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> - * @throws NullPointerException if any argument is null - */ - public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { - MemberName field = resolveOrFail(refc, name, type, false); - checkSecurityManager(refc, field); // stack walk magic: do not refactor - return makeAccessor(refc, field, false, true, 0); - } - private MethodHandle resolveSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { - MemberName field = resolveOrFail(refc, name, type, false); - return makeAccessor(refc, field, false, true, 0); - } - - /** - * Produces a method handle giving read access to a static field. - * The type of the method handle will have a return type of the field's - * value type. - * The method handle will take no arguments. - * Access checking is performed immediately on behalf of the lookup class. - * @param refc the class or interface from which the method is accessed - * @param name the field's name - * @param type the field's type - * @return a method handle which can load values from the field - * @throws NoSuchFieldException if the field does not exist - * @throws IllegalAccessException if access checking fails, or if the field is not {@code static} - * @exception SecurityException if a security manager is present and it - * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> - * @throws NullPointerException if any argument is null - */ - public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { - MemberName field = resolveOrFail(refc, name, type, true); - checkSecurityManager(refc, field); // stack walk magic: do not refactor - return makeAccessor(refc, field, false, false, 1); - } - private MethodHandle resolveStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { - MemberName field = resolveOrFail(refc, name, type, true); - return makeAccessor(refc, field, false, false, 1); - } - - /** - * Produces a method handle giving write access to a static field. - * The type of the method handle will have a void return type. - * The method handle will take a single - * argument, of the field's value type, the value to be stored. - * Access checking is performed immediately on behalf of the lookup class. - * @param refc the class or interface from which the method is accessed - * @param name the field's name - * @param type the field's type - * @return a method handle which can store values into the field - * @throws NoSuchFieldException if the field does not exist - * @throws IllegalAccessException if access checking fails, or if the field is not {@code static} - * @exception SecurityException if a security manager is present and it - * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> - * @throws NullPointerException if any argument is null - */ - public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { - MemberName field = resolveOrFail(refc, name, type, true); - checkSecurityManager(refc, field); // stack walk magic: do not refactor - return makeAccessor(refc, field, false, true, 1); - } - private MethodHandle resolveStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { - MemberName field = resolveOrFail(refc, name, type, true); - return makeAccessor(refc, field, false, true, 1); - } - - /** - * Produces an early-bound method handle for a non-static method. - * The receiver must have a supertype {@code defc} in which a method - * of the given name and type is accessible to the lookup class. - * The method and all its argument types must be accessible to the lookup class. - * The type of the method handle will be that of the method, - * without any insertion of an additional receiver parameter. - * The given receiver will be bound into the method handle, - * so that every call to the method handle will invoke the - * requested method on the given receiver. - * <p> - * The returned method handle will have - * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if - * the method's variable arity modifier bit ({@code 0x0080}) is set - * <em>and</em> the trailing array argument is not the only argument. - * (If the trailing array argument is the only argument, - * the given receiver value will be bound to it.) - * <p> - * This is equivalent to the following code: - * <blockquote><pre> -import static java.lang.invoke.MethodHandles.*; -import static java.lang.invoke.MethodType.*; -... -MethodHandle mh0 = lookup().{@link #findVirtual findVirtual}(defc, name, type); -MethodHandle mh1 = mh0.{@link MethodHandle#bindTo bindTo}(receiver); -MethodType mt1 = mh1.type(); -if (mh0.isVarargsCollector()) - mh1 = mh1.asVarargsCollector(mt1.parameterType(mt1.parameterCount()-1)); -return mh1; - * </pre></blockquote> - * where {@code defc} is either {@code receiver.getClass()} or a super - * type of that class, in which the requested method is accessible - * to the lookup class. - * (Note that {@code bindTo} does not preserve variable arity.) - * @param receiver the object from which the method is accessed - * @param name the name of the method - * @param type the type of the method, with the receiver argument omitted - * @return the desired method handle - * @throws NoSuchMethodException if the method does not exist - * @throws IllegalAccessException if access checking fails - * or if the method's variable arity modifier bit - * is set and {@code asVarargsCollector} fails - * @exception SecurityException if a security manager is present and it - * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> - * @throws NullPointerException if any argument is null - */ - public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { - Class<? extends Object> refc = receiver.getClass(); // may get NPE - MemberName method = resolveOrFail(refc, name, type, false); - checkSecurityManager(refc, method); // stack walk magic: do not refactor - checkMethod(refc, method, false); - MethodHandle dmh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull()); - MethodHandle bmh = MethodHandleImpl.bindReceiver(dmh, receiver); - if (bmh == null) - throw method.makeAccessException("no access", this); - return fixVarargs(bmh, dmh); - } - - /** - * Makes a direct method handle to <i>m</i>, if the lookup class has permission. - * If <i>m</i> is non-static, the receiver argument is treated as an initial argument. - * If <i>m</i> is virtual, overriding is respected on every call. - * Unlike the Core Reflection API, exceptions are <em>not</em> wrapped. - * The type of the method handle will be that of the method, - * with the receiver type prepended (but only if it is non-static). - * If the method's {@code accessible} flag is not set, - * access checking is performed immediately on behalf of the lookup class. - * If <i>m</i> is not public, do not share the resulting handle with untrusted parties. - * <p> - * The returned method handle will have - * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if - * the method's variable arity modifier bit ({@code 0x0080}) is set. - * @param m the reflected method - * @return a method handle which can invoke the reflected method - * @throws IllegalAccessException if access checking fails - * or if the method's variable arity modifier bit - * is set and {@code asVarargsCollector} fails - * @throws NullPointerException if the argument is null - */ - public MethodHandle unreflect(Method m) throws IllegalAccessException { - MemberName method = new MemberName(m); - assert(method.isMethod()); - if (m.isAccessible()) - return MethodHandleImpl.findMethod(method, true, /*no lookupClass*/ null); - checkMethod(method.getDeclaringClass(), method, method.isStatic()); - MethodHandle mh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull()); - return restrictProtectedReceiver(method, mh); - } - - /** - * Produces a method handle for a reflected method. - * It will bypass checks for overriding methods on the receiver, - * as if by a {@code invokespecial} instruction from within the {@code specialCaller}. - * The type of the method handle will be that of the method, - * with the special caller type prepended (and <em>not</em> the receiver of the method). - * If the method's {@code accessible} flag is not set, - * access checking is performed immediately on behalf of the lookup class, - * as if {@code invokespecial} instruction were being linked. - * <p> - * The returned method handle will have - * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if - * the method's variable arity modifier bit ({@code 0x0080}) is set. - * @param m the reflected method - * @param specialCaller the class nominally calling the method - * @return a method handle which can invoke the reflected method - * @throws IllegalAccessException if access checking fails - * or if the method's variable arity modifier bit - * is set and {@code asVarargsCollector} fails - * @throws NullPointerException if any argument is null - */ - public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException { - checkSpecialCaller(specialCaller); - MemberName method = new MemberName(m); - assert(method.isMethod()); - // ignore m.isAccessible: this is a new kind of access - checkMethod(m.getDeclaringClass(), method, false); - MethodHandle mh = MethodHandleImpl.findMethod(method, false, lookupClassOrNull()); - return restrictReceiver(method, mh, specialCaller); - } - - /** - * Produces a method handle for a reflected constructor. - * The type of the method handle will be that of the constructor, - * with the return type changed to the declaring class. - * The method handle will perform a {@code newInstance} operation, - * creating a new instance of the constructor's class on the - * arguments passed to the method handle. - * <p> - * If the constructor's {@code accessible} flag is not set, - * access checking is performed immediately on behalf of the lookup class. - * <p> - * The returned method handle will have - * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if - * the constructor's variable arity modifier bit ({@code 0x0080}) is set. - * @param c the reflected constructor - * @return a method handle which can invoke the reflected constructor - * @throws IllegalAccessException if access checking fails - * or if the method's variable arity modifier bit - * is set and {@code asVarargsCollector} fails - * @throws NullPointerException if the argument is null - */ - public MethodHandle unreflectConstructor(Constructor c) throws IllegalAccessException { - MemberName ctor = new MemberName(c); - assert(ctor.isConstructor()); - MethodHandle rawCtor; - if (c.isAccessible()) { - rawCtor = MethodHandleImpl.findMethod(ctor, false, /*no lookupClass*/ null); - } else { - checkAccess(c.getDeclaringClass(), ctor); - rawCtor = MethodHandleImpl.findMethod(ctor, false, lookupClassOrNull()); - } - MethodHandle allocator = MethodHandleImpl.makeAllocator(rawCtor); - return fixVarargs(allocator, rawCtor); - } - - /** - * Produces a method handle giving read access to a reflected field. - * The type of the method handle will have a return type of the field's - * value type. - * If the field is static, the method handle will take no arguments. - * Otherwise, its single argument will be the instance containing - * the field. - * If the field's {@code accessible} flag is not set, - * access checking is performed immediately on behalf of the lookup class. - * @param f the reflected field - * @return a method handle which can load values from the reflected field - * @throws IllegalAccessException if access checking fails - * @throws NullPointerException if the argument is null - */ - public MethodHandle unreflectGetter(Field f) throws IllegalAccessException { - return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), false, -1); - } - - /** - * Produces a method handle giving write access to a reflected field. - * The type of the method handle will have a void return type. - * If the field is static, the method handle will take a single - * argument, of the field's value type, the value to be stored. - * Otherwise, the two arguments will be the instance containing - * the field, and the value to be stored. - * If the field's {@code accessible} flag is not set, - * access checking is performed immediately on behalf of the lookup class. - * @param f the reflected field - * @return a method handle which can store values into the reflected field - * @throws IllegalAccessException if access checking fails - * @throws NullPointerException if the argument is null - */ - public MethodHandle unreflectSetter(Field f) throws IllegalAccessException { - return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), true, -1); - } - - /// Helper methods, all package-private. - - MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) throws NoSuchFieldException, IllegalAccessException { - checkSymbolicClass(refc); // do this before attempting to resolve - name.getClass(); type.getClass(); // NPE - int mods = (isStatic ? Modifier.STATIC : 0); - return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull(), - NoSuchFieldException.class); - } - - MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) throws NoSuchMethodException, IllegalAccessException { - checkSymbolicClass(refc); // do this before attempting to resolve - name.getClass(); type.getClass(); // NPE - int mods = (isStatic ? Modifier.STATIC : 0); - return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull(), - NoSuchMethodException.class); - } - - MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic, - boolean searchSupers, Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException { - checkSymbolicClass(refc); // do this before attempting to resolve - name.getClass(); type.getClass(); // NPE - int mods = (isStatic ? Modifier.STATIC : 0); - return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), searchSupers, specialCaller, - NoSuchMethodException.class); - } - - void checkSymbolicClass(Class<?> refc) throws IllegalAccessException { - Class<?> caller = lookupClassOrNull(); - if (caller != null && !VerifyAccess.isClassAccessible(refc, caller, allowedModes)) - throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this); - } - - /** - * Perform necessary <a href="MethodHandles.Lookup.html#secmgr">access checks</a>. - * This function performs stack walk magic: do not refactor it. - */ - void checkSecurityManager(Class<?> refc, MemberName m) { - if (noSecurityCheck) return; - SecurityManager smgr = System.getSecurityManager(); - if (smgr == null) return; - if (allowedModes == TRUSTED) return; - // Step 1: - smgr.checkMemberAccess(refc, Member.PUBLIC); - // Step 2: - Class<?> callerClass = ((allowedModes & PRIVATE) != 0 - ? lookupClass // for strong access modes, no extra check - // next line does stack walk magic; do not refactor: - : getCallerClassAtEntryPoint(true)); - if (!VerifyAccess.classLoaderIsAncestor(lookupClass, refc) || - (callerClass != lookupClass && - !VerifyAccess.classLoaderIsAncestor(callerClass, refc))) - smgr.checkPackageAccess(VerifyAccess.getPackageName(refc)); - // Step 3: - if (m.isPublic()) return; - Class<?> defc = m.getDeclaringClass(); - smgr.checkMemberAccess(defc, Member.DECLARED); // STACK WALK HERE - // Step 4: - if (defc != refc) - smgr.checkPackageAccess(VerifyAccess.getPackageName(defc)); - - // Comment from SM.checkMemberAccess, where which=DECLARED: - /* - * stack depth of 4 should be the caller of one of the - * methods in java.lang.Class that invoke checkMember - * access. The stack should look like: - * - * someCaller [3] - * java.lang.Class.someReflectionAPI [2] - * java.lang.Class.checkMemberAccess [1] - * SecurityManager.checkMemberAccess [0] - * - */ - // For us it is this stack: - // someCaller [3] - // Lookup.findSomeMember [2] - // Lookup.checkSecurityManager [1] - // SecurityManager.checkMemberAccess [0] - } - - void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) throws IllegalAccessException { - String message; - if (m.isConstructor()) - message = "expected a method, not a constructor"; - else if (!m.isMethod()) - message = "expected a method"; - else if (wantStatic != m.isStatic()) - message = wantStatic ? "expected a static method" : "expected a non-static method"; - else - { checkAccess(refc, m); return; } - throw m.makeAccessException(message, this); - } - - void checkAccess(Class<?> refc, MemberName m) throws IllegalAccessException { - int allowedModes = this.allowedModes; - if (allowedModes == TRUSTED) return; - int mods = m.getModifiers(); - if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()) && allowedModes != 0) - return; // common case - int requestedModes = fixmods(mods); // adjust 0 => PACKAGE - if ((requestedModes & allowedModes) != 0 - && VerifyAccess.isMemberAccessible(refc, m.getDeclaringClass(), - mods, lookupClass(), allowedModes)) - return; - if (((requestedModes & ~allowedModes) & PROTECTED) != 0 - && (allowedModes & PACKAGE) != 0 - && VerifyAccess.isSamePackage(m.getDeclaringClass(), lookupClass())) - // Protected members can also be checked as if they were package-private. - return; - throw m.makeAccessException(accessFailedMessage(refc, m), this); - } - - String accessFailedMessage(Class<?> refc, MemberName m) { - Class<?> defc = m.getDeclaringClass(); - int mods = m.getModifiers(); - // check the class first: - boolean classOK = (Modifier.isPublic(defc.getModifiers()) && - (defc == refc || - Modifier.isPublic(refc.getModifiers()))); - if (!classOK && (allowedModes & PACKAGE) != 0) { - classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), ALL_MODES) && - (defc == refc || - VerifyAccess.isClassAccessible(refc, lookupClass(), ALL_MODES))); - } - if (!classOK) - return "class is not public"; - if (Modifier.isPublic(mods)) - return "access to public member failed"; // (how?) - if (Modifier.isPrivate(mods)) - return "member is private"; - if (Modifier.isProtected(mods)) - return "member is protected"; - return "member is private to package"; - } - - private static final boolean ALLOW_NESTMATE_ACCESS = false; - - void checkSpecialCaller(Class<?> specialCaller) throws IllegalAccessException { - if (allowedModes == TRUSTED) return; - if ((allowedModes & PRIVATE) == 0 - || (specialCaller != lookupClass() - && !(ALLOW_NESTMATE_ACCESS && - VerifyAccess.isSamePackageMember(specialCaller, lookupClass())))) - throw new MemberName(specialCaller). - makeAccessException("no private access for invokespecial", this); - } - - MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) throws IllegalAccessException { - // The accessing class only has the right to use a protected member - // on itself or a subclass. Enforce that restriction, from JVMS 5.4.4, etc. - if (!method.isProtected() || method.isStatic() - || allowedModes == TRUSTED - || method.getDeclaringClass() == lookupClass() - || VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass()) - || (ALLOW_NESTMATE_ACCESS && - VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass()))) - return mh; - else - return restrictReceiver(method, mh, lookupClass()); - } - MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) throws IllegalAccessException { - assert(!method.isStatic()); - Class<?> defc = method.getDeclaringClass(); // receiver type of mh is too wide - if (defc.isInterface() || !defc.isAssignableFrom(caller)) { - throw method.makeAccessException("caller class must be a subclass below the method", caller); - } - MethodType rawType = mh.type(); - if (rawType.parameterType(0) == caller) return mh; - MethodType narrowType = rawType.changeParameterType(0, caller); - MethodHandle narrowMH = MethodHandleImpl.convertArguments(mh, narrowType, rawType, 0); - return fixVarargs(narrowMH, mh); - } - - MethodHandle makeAccessor(Class<?> refc, MemberName field, - boolean trusted, boolean isSetter, - int checkStatic) throws IllegalAccessException { - assert(field.isField()); - if (checkStatic >= 0 && (checkStatic != 0) != field.isStatic()) - throw field.makeAccessException((checkStatic != 0) - ? "expected a static field" - : "expected a non-static field", this); - if (trusted) - return MethodHandleImpl.accessField(field, isSetter, /*no lookupClass*/ null); - checkAccess(refc, field); - MethodHandle mh = MethodHandleImpl.accessField(field, isSetter, lookupClassOrNull()); - return restrictProtectedReceiver(field, mh); - } - - /** Hook called from the JVM (via MethodHandleNatives) to link MH constants: - */ - /*non-public*/ - MethodHandle linkMethodHandleConstant(int refKind, Class<?> defc, String name, Object type) throws ReflectiveOperationException { - switch (refKind) { - case REF_getField: return resolveGetter( defc, name, (Class<?>) type ); - case REF_getStatic: return resolveStaticGetter( defc, name, (Class<?>) type ); - case REF_putField: return resolveSetter( defc, name, (Class<?>) type ); - case REF_putStatic: return resolveStaticSetter( defc, name, (Class<?>) type ); - case REF_invokeVirtual: return resolveVirtual( defc, name, (MethodType) type ); - case REF_invokeStatic: return resolveStatic( defc, name, (MethodType) type ); - case REF_invokeSpecial: return resolveSpecial( defc, name, (MethodType) type ); - case REF_newInvokeSpecial: return resolveConstructor( defc, (MethodType) type ); - case REF_invokeInterface: return resolveVirtual( defc, name, (MethodType) type ); - } - // oops - throw new ReflectiveOperationException("bad MethodHandle constant #"+refKind+" "+name+" : "+type); - } - } - - /** - * Produces a method handle giving read access to elements of an array. - * The type of the method handle will have a return type of the array's - * element type. Its first argument will be the array type, - * and the second will be {@code int}. - * @param arrayClass an array type - * @return a method handle which can load values from the given array type - * @throws NullPointerException if the argument is null - * @throws IllegalArgumentException if arrayClass is not an array type - */ - public static - MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException { - return MethodHandleImpl.accessArrayElement(arrayClass, false); - } - - /** - * Produces a method handle giving write access to elements of an array. - * The type of the method handle will have a void return type. - * Its last argument will be the array's element type. - * The first and second arguments will be the array type and int. - * @return a method handle which can store values into the array type - * @throws NullPointerException if the argument is null - * @throws IllegalArgumentException if arrayClass is not an array type - */ - public static - MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException { - return MethodHandleImpl.accessArrayElement(arrayClass, true); - } - - /// method handle invocation (reflective style) - - /** - * Produces a method handle which will invoke any method handle of the - * given {@code type}, with a given number of trailing arguments replaced by - * a single trailing {@code Object[]} array. - * The resulting invoker will be a method handle with the following - * arguments: - * <ul> - * <li>a single {@code MethodHandle} target - * <li>zero or more leading values (counted by {@code leadingArgCount}) - * <li>an {@code Object[]} array containing trailing arguments - * </ul> - * <p> - * The invoker will invoke its target like a call to {@link MethodHandle#invoke invoke} with - * the indicated {@code type}. - * That is, if the target is exactly of the given {@code type}, it will behave - * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle#asType asType} - * is used to convert the target to the required {@code type}. - * <p> - * The type of the returned invoker will not be the given {@code type}, but rather - * will have all parameters except the first {@code leadingArgCount} - * replaced by a single array of type {@code Object[]}, which will be - * the final parameter. - * <p> - * Before invoking its target, the invoker will spread the final array, apply - * reference casts as necessary, and unbox and widen primitive arguments. - * <p> - * This method is equivalent to the following code (though it may be more efficient): - * <p><blockquote><pre> -MethodHandle invoker = MethodHandles.invoker(type); -int spreadArgCount = type.parameterCount() - leadingArgCount; -invoker = invoker.asSpreader(Object[].class, spreadArgCount); -return invoker; - * </pre></blockquote> - * <p> - * This method throws no reflective or security exceptions. - * @param type the desired target type - * @param leadingArgCount number of fixed arguments, to be passed unchanged to the target - * @return a method handle suitable for invoking any method handle of the given type - * @throws NullPointerException if {@code type} is null - * @throws IllegalArgumentException if {@code leadingArgCount} is not in - * the range from 0 to {@code type.parameterCount()} inclusive - */ - static public - MethodHandle spreadInvoker(MethodType type, int leadingArgCount) { - if (leadingArgCount < 0 || leadingArgCount > type.parameterCount()) - throw new IllegalArgumentException("bad argument count "+leadingArgCount); - return type.invokers().spreadInvoker(leadingArgCount); - } - - /** - * Produces a special <em>invoker method handle</em> which can be used to - * invoke any method handle of the given type, as if by {@link MethodHandle#invokeExact invokeExact}. - * The resulting invoker will have a type which is - * exactly equal to the desired type, except that it will accept - * an additional leading argument of type {@code MethodHandle}. - * <p> - * This method is equivalent to the following code (though it may be more efficient): - * <p><blockquote><pre> -publicLookup().findVirtual(MethodHandle.class, "invokeExact", type) - * </pre></blockquote> - * - * <p style="font-size:smaller;"> - * <em>Discussion:</em> - * Invoker method handles can be useful when working with variable method handles - * of unknown types. - * For example, to emulate an {@code invokeExact} call to a variable method - * handle {@code M}, extract its type {@code T}, - * look up the invoker method {@code X} for {@code T}, - * and call the invoker method, as {@code X.invoke(T, A...)}. - * (It would not work to call {@code X.invokeExact}, since the type {@code T} - * is unknown.) - * If spreading, collecting, or other argument transformations are required, - * they can be applied once to the invoker {@code X} and reused on many {@code M} - * method handle values, as long as they are compatible with the type of {@code X}. - * <p> - * <em>(Note: The invoker method is not available via the Core Reflection API. - * An attempt to call {@linkplain java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke} - * on the declared {@code invokeExact} or {@code invoke} method will raise an - * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em> - * <p> - * This method throws no reflective or security exceptions. - * @param type the desired target type - * @return a method handle suitable for invoking any method handle of the given type - */ - static public - MethodHandle exactInvoker(MethodType type) { - return type.invokers().exactInvoker(); - } - - /** - * Produces a special <em>invoker method handle</em> which can be used to - * invoke any method handle compatible with the given type, as if by {@link MethodHandle#invoke invoke}. - * The resulting invoker will have a type which is - * exactly equal to the desired type, except that it will accept - * an additional leading argument of type {@code MethodHandle}. - * <p> - * Before invoking its target, if the target differs from the expected type, - * the invoker will apply reference casts as - * necessary and box, unbox, or widen primitive values, as if by {@link MethodHandle#asType asType}. - * Similarly, the return value will be converted as necessary. - * If the target is a {@linkplain MethodHandle#asVarargsCollector variable arity method handle}, - * the required arity conversion will be made, again as if by {@link MethodHandle#asType asType}. - * <p> - * A {@linkplain MethodType#genericMethodType general method type}, - * mentions only {@code Object} arguments and return values. - * An invoker for such a type is capable of calling any method handle - * of the same arity as the general type. - * <p> - * This method is equivalent to the following code (though it may be more efficient): - * <p><blockquote><pre> -publicLookup().findVirtual(MethodHandle.class, "invoke", type) - * </pre></blockquote> - * <p> - * This method throws no reflective or security exceptions. - * @param type the desired target type - * @return a method handle suitable for invoking any method handle convertible to the given type - */ - static public - MethodHandle invoker(MethodType type) { - return type.invokers().generalInvoker(); - } - - /** - * Perform value checking, exactly as if for an adapted method handle. - * It is assumed that the given value is either null, of type T0, - * or (if T0 is primitive) of the wrapper class corresponding to T0. - * The following checks and conversions are made: - * <ul> - * <li>If T0 and T1 are references, then a cast to T1 is applied. - * (The types do not need to be related in any particular way.) - * <li>If T0 and T1 are primitives, then a widening or narrowing - * conversion is applied, if one exists. - * <li>If T0 is a primitive and T1 a reference, and - * T0 has a wrapper class TW, a boxing conversion to TW is applied, - * possibly followed by a reference conversion. - * T1 must be TW or a supertype. - * <li>If T0 is a reference and T1 a primitive, and - * T1 has a wrapper class TW, an unboxing conversion is applied, - * possibly preceded by a reference conversion. - * T0 must be TW or a supertype. - * <li>If T1 is void, the return value is discarded - * <li>If T0 is void and T1 a reference, a null value is introduced. - * <li>If T0 is void and T1 a primitive, a zero value is introduced. - * </ul> - * If the value is discarded, null will be returned. - * @param valueType - * @param value - * @return the value, converted if necessary - * @throws java.lang.ClassCastException if a cast fails - */ - // FIXME: This is used in just one place. Refactor away. - static - <T0, T1> T1 checkValue(Class<T0> t0, Class<T1> t1, Object value) - throws ClassCastException - { - if (t0 == t1) { - // no conversion needed; just reassert the same type - if (t0.isPrimitive()) - return Wrapper.asPrimitiveType(t1).cast(value); - else - return Wrapper.OBJECT.convert(value, t1); - } - boolean prim0 = t0.isPrimitive(), prim1 = t1.isPrimitive(); - if (!prim0) { - // check contract with caller - Wrapper.OBJECT.convert(value, t0); - if (!prim1) { - return Wrapper.OBJECT.convert(value, t1); - } - // convert reference to primitive by unboxing - Wrapper w1 = Wrapper.forPrimitiveType(t1); - return w1.convert(value, t1); - } - // check contract with caller: - Wrapper.asWrapperType(t0).cast(value); - Wrapper w1 = Wrapper.forPrimitiveType(t1); - return w1.convert(value, t1); - } - - // FIXME: Delete this. It is used only for insertArguments & bindTo. - // Replace by a more standard check. - static - Object checkValue(Class<?> T1, Object value) - throws ClassCastException - { - Class<?> T0; - if (value == null) - T0 = Object.class; - else - T0 = value.getClass(); - return checkValue(T0, T1, value); - } - - /// method handle modification (creation from other method handles) - - /** - * Produces a method handle which adapts the type of the - * given method handle to a new type by pairwise argument and return type conversion. - * The original type and new type must have the same number of arguments. - * The resulting method handle is guaranteed to report a type - * which is equal to the desired new type. - * <p> - * If the original type and new type are equal, returns target. - * <p> - * The same conversions are allowed as for {@link MethodHandle#asType MethodHandle.asType}, - * and some additional conversions are also applied if those conversions fail. - * Given types <em>T0</em>, <em>T1</em>, one of the following conversions is applied - * if possible, before or instead of any conversions done by {@code asType}: - * <ul> - * <li>If <em>T0</em> and <em>T1</em> are references, and <em>T1</em> is an interface type, - * then the value of type <em>T0</em> is passed as a <em>T1</em> without a cast. - * (This treatment of interfaces follows the usage of the bytecode verifier.) - * <li>If <em>T0</em> is boolean and <em>T1</em> is another primitive, - * the boolean is converted to a byte value, 1 for true, 0 for false. - * (This treatment follows the usage of the bytecode verifier.) - * <li>If <em>T1</em> is boolean and <em>T0</em> is another primitive, - * <em>T0</em> is converted to byte via Java casting conversion (JLS 5.5), - * and the low order bit of the result is tested, as if by {@code (x & 1) != 0}. - * <li>If <em>T0</em> and <em>T1</em> are primitives other than boolean, - * then a Java casting conversion (JLS 5.5) is applied. - * (Specifically, <em>T0</em> will convert to <em>T1</em> by - * widening and/or narrowing.) - * <li>If <em>T0</em> is a reference and <em>T1</em> a primitive, an unboxing - * conversion will be applied at runtime, possibly followed - * by a Java casting conversion (JLS 5.5) on the primitive value, - * possibly followed by a conversion from byte to boolean by testing - * the low-order bit. - * <li>If <em>T0</em> is a reference and <em>T1</em> a primitive, - * and if the reference is null at runtime, a zero value is introduced. - * </ul> - * @param target the method handle to invoke after arguments are retyped - * @param newType the expected type of the new method handle - * @return a method handle which delegates to the target after performing - * any necessary argument conversions, and arranges for any - * necessary return value conversions - * @throws NullPointerException if either argument is null - * @throws WrongMethodTypeException if the conversion cannot be made - * @see MethodHandle#asType - */ - public static - MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) { - return MethodHandleImpl.convertArguments(target, newType, 2); - } - - /** - * Produces a method handle which adapts the calling sequence of the - * given method handle to a new type, by reordering the arguments. - * The resulting method handle is guaranteed to report a type - * which is equal to the desired new type. - * <p> - * The given array controls the reordering. - * Call {@code #I} the number of incoming parameters (the value - * {@code newType.parameterCount()}, and call {@code #O} the number - * of outgoing parameters (the value {@code target.type().parameterCount()}). - * Then the length of the reordering array must be {@code #O}, - * and each element must be a non-negative number less than {@code #I}. - * For every {@code N} less than {@code #O}, the {@code N}-th - * outgoing argument will be taken from the {@code I}-th incoming - * argument, where {@code I} is {@code reorder[N]}. - * <p> - * No argument or return value conversions are applied. - * The type of each incoming argument, as determined by {@code newType}, - * must be identical to the type of the corresponding outgoing parameter - * or parameters in the target method handle. - * The return type of {@code newType} must be identical to the return - * type of the original target. - * <p> - * The reordering array need not specify an actual permutation. - * An incoming argument will be duplicated if its index appears - * more than once in the array, and an incoming argument will be dropped - * if its index does not appear in the array. - * As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments}, - * incoming arguments which are not mentioned in the reordering array - * are may be any type, as determined only by {@code newType}. - * <blockquote><pre> -import static java.lang.invoke.MethodHandles.*; -import static java.lang.invoke.MethodType.*; -... -MethodType intfn1 = methodType(int.class, int.class); -MethodType intfn2 = methodType(int.class, int.class, int.class); -MethodHandle sub = ... {int x, int y => x-y} ...; -assert(sub.type().equals(intfn2)); -MethodHandle sub1 = permuteArguments(sub, intfn2, 0, 1); -MethodHandle rsub = permuteArguments(sub, intfn2, 1, 0); -assert((int)rsub.invokeExact(1, 100) == 99); -MethodHandle add = ... {int x, int y => x+y} ...; -assert(add.type().equals(intfn2)); -MethodHandle twice = permuteArguments(add, intfn1, 0, 0); -assert(twice.type().equals(intfn1)); -assert((int)twice.invokeExact(21) == 42); - * </pre></blockquote> - * @param target the method handle to invoke after arguments are reordered - * @param newType the expected type of the new method handle - * @param reorder an index array which controls the reordering - * @return a method handle which delegates to the target after it - * drops unused arguments and moves and/or duplicates the other arguments - * @throws NullPointerException if any argument is null - * @throws IllegalArgumentException if the index array length is not equal to - * the arity of the target, or if any index array element - * not a valid index for a parameter of {@code newType}, - * or if two corresponding parameter types in - * {@code target.type()} and {@code newType} are not identical, - */ - public static - MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) { - MethodType oldType = target.type(); - checkReorder(reorder, newType, oldType); - return MethodHandleImpl.permuteArguments(target, - newType, oldType, - reorder); - } - - private static void checkReorder(int[] reorder, MethodType newType, MethodType oldType) { - if (newType.returnType() != oldType.returnType()) - throw newIllegalArgumentException("return types do not match", - oldType, newType); - if (reorder.length == oldType.parameterCount()) { - int limit = newType.parameterCount(); - boolean bad = false; - for (int j = 0; j < reorder.length; j++) { - int i = reorder[j]; - if (i < 0 || i >= limit) { - bad = true; break; - } - Class<?> src = newType.parameterType(i); - Class<?> dst = oldType.parameterType(j); - if (src != dst) - throw newIllegalArgumentException("parameter types do not match after reorder", - oldType, newType); - } - if (!bad) return; - } - throw newIllegalArgumentException("bad reorder array: "+Arrays.toString(reorder)); - } - - /** - * Produces a method handle of the requested return type which returns the given - * constant value every time it is invoked. - * <p> - * Before the method handle is returned, the passed-in value is converted to the requested type. - * If the requested type is primitive, widening primitive conversions are attempted, - * else reference conversions are attempted. - * <p>The returned method handle is equivalent to {@code identity(type).bindTo(value)}. - * @param type the return type of the desired method handle - * @param value the value to return - * @return a method handle of the given return type and no arguments, which always returns the given value - * @throws NullPointerException if the {@code type} argument is null - * @throws ClassCastException if the value cannot be converted to the required return type - * @throws IllegalArgumentException if the given type is {@code void.class} - */ - public static - MethodHandle constant(Class<?> type, Object value) { - if (type.isPrimitive()) { - if (type == void.class) - throw newIllegalArgumentException("void type"); - Wrapper w = Wrapper.forPrimitiveType(type); - return insertArguments(identity(type), 0, w.convert(value, type)); - } else { - return identity(type).bindTo(type.cast(value)); - } - } - - /** - * Produces a method handle which returns its sole argument when invoked. - * @param type the type of the sole parameter and return value of the desired method handle - * @return a unary method handle which accepts and returns the given type - * @throws NullPointerException if the argument is null - * @throws IllegalArgumentException if the given type is {@code void.class} - */ - public static - MethodHandle identity(Class<?> type) { - if (type == void.class) - throw newIllegalArgumentException("void type"); - else if (type == Object.class) - return ValueConversions.identity(); - else if (type.isPrimitive()) - return ValueConversions.identity(Wrapper.forPrimitiveType(type)); - else - return AdapterMethodHandle.makeRetypeRaw( - MethodType.methodType(type, type), ValueConversions.identity()); - } - - /** - * Provides a target method handle with one or more <em>bound arguments</em> - * in advance of the method handle's invocation. - * The formal parameters to the target corresponding to the bound - * arguments are called <em>bound parameters</em>. - * Returns a new method handle which saves away the bound arguments. - * When it is invoked, it receives arguments for any non-bound parameters, - * binds the saved arguments to their corresponding parameters, - * and calls the original target. - * <p> - * The type of the new method handle will drop the types for the bound - * parameters from the original target type, since the new method handle - * will no longer require those arguments to be supplied by its callers. - * <p> - * Each given argument object must match the corresponding bound parameter type. - * If a bound parameter type is a primitive, the argument object - * must be a wrapper, and will be unboxed to produce the primitive value. - * <p> - * The {@code pos} argument selects which parameters are to be bound. - * It may range between zero and <i>N-L</i> (inclusively), - * where <i>N</i> is the arity of the target method handle - * and <i>L</i> is the length of the values array. - * @param target the method handle to invoke after the argument is inserted - * @param pos where to insert the argument (zero for the first) - * @param values the series of arguments to insert - * @return a method handle which inserts an additional argument, - * before calling the original method handle - * @throws NullPointerException if the target or the {@code values} array is null - * @see MethodHandle#bindTo - */ - public static - MethodHandle insertArguments(MethodHandle target, int pos, Object... values) { - int insCount = values.length; - MethodType oldType = target.type(); - int outargs = oldType.parameterCount(); - int inargs = outargs - insCount; - if (inargs < 0) - throw newIllegalArgumentException("too many values to insert"); - if (pos < 0 || pos > inargs) - throw newIllegalArgumentException("no argument type to append"); - MethodHandle result = target; - for (int i = 0; i < insCount; i++) { - Object value = values[i]; - Class<?> valueType = oldType.parameterType(pos+i); - value = checkValue(valueType, value); - if (pos == 0 && !valueType.isPrimitive()) { - // At least for now, make bound method handles a special case. - MethodHandle bmh = MethodHandleImpl.bindReceiver(result, value); - if (bmh != null) { - result = bmh; - continue; - } - // else fall through to general adapter machinery - } - result = MethodHandleImpl.bindArgument(result, pos, value); - } - return result; - } - - /** - * Produces a method handle which will discard some dummy arguments - * before calling some other specified <i>target</i> method handle. - * The type of the new method handle will be the same as the target's type, - * except it will also include the dummy argument types, - * at some given position. - * <p> - * The {@code pos} argument may range between zero and <i>N</i>, - * where <i>N</i> is the arity of the target. - * If {@code pos} is zero, the dummy arguments will precede - * the target's real arguments; if {@code pos} is <i>N</i> - * they will come after. - * <p> - * <b>Example:</b> - * <p><blockquote><pre> -import static java.lang.invoke.MethodHandles.*; -import static java.lang.invoke.MethodType.*; -... -MethodHandle cat = lookup().findVirtual(String.class, - "concat", methodType(String.class, String.class)); -assertEquals("xy", (String) cat.invokeExact("x", "y")); -MethodType bigType = cat.type().insertParameterTypes(0, int.class, String.class); -MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2)); -assertEquals(bigType, d0.type()); -assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z")); - * </pre></blockquote> - * <p> - * This method is also equivalent to the following code: - * <p><blockquote><pre> - * {@link #dropArguments(MethodHandle,int,Class...) dropArguments}(target, pos, valueTypes.toArray(new Class[0])) - * </pre></blockquote> - * @param target the method handle to invoke after the arguments are dropped - * @param valueTypes the type(s) of the argument(s) to drop - * @param pos position of first argument to drop (zero for the leftmost) - * @return a method handle which drops arguments of the given types, - * before calling the original method handle - * @throws NullPointerException if the target is null, - * or if the {@code valueTypes} list or any of its elements is null - * @throws IllegalArgumentException if any element of {@code valueTypes} is {@code void.class}, - * or if {@code pos} is negative or greater than the arity of the target, - * or if the new method handle's type would have too many parameters - */ - public static - MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) { - MethodType oldType = target.type(); // get NPE - if (valueTypes.size() == 0) return target; - int outargs = oldType.parameterCount(); - int inargs = outargs + valueTypes.size(); - if (pos < 0 || pos >= inargs) - throw newIllegalArgumentException("no argument type to remove"); - ArrayList<Class<?>> ptypes = - new ArrayList<Class<?>>(oldType.parameterList()); - ptypes.addAll(pos, valueTypes); - MethodType newType = MethodType.methodType(oldType.returnType(), ptypes); - return MethodHandleImpl.dropArguments(target, newType, pos); - } - - /** - * Produces a method handle which will discard some dummy arguments - * before calling some other specified <i>target</i> method handle. - * The type of the new method handle will be the same as the target's type, - * except it will also include the dummy argument types, - * at some given position. - * <p> - * The {@code pos} argument may range between zero and <i>N</i>, - * where <i>N</i> is the arity of the target. - * If {@code pos} is zero, the dummy arguments will precede - * the target's real arguments; if {@code pos} is <i>N</i> - * they will come after. - * <p> - * <b>Example:</b> - * <p><blockquote><pre> -import static java.lang.invoke.MethodHandles.*; -import static java.lang.invoke.MethodType.*; -... -MethodHandle cat = lookup().findVirtual(String.class, - "concat", methodType(String.class, String.class)); -assertEquals("xy", (String) cat.invokeExact("x", "y")); -MethodHandle d0 = dropArguments(cat, 0, String.class); -assertEquals("yz", (String) d0.invokeExact("x", "y", "z")); -MethodHandle d1 = dropArguments(cat, 1, String.class); -assertEquals("xz", (String) d1.invokeExact("x", "y", "z")); -MethodHandle d2 = dropArguments(cat, 2, String.class); -assertEquals("xy", (String) d2.invokeExact("x", "y", "z")); -MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class); -assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z")); - * </pre></blockquote> - * <p> - * This method is also equivalent to the following code: - * <p><blockquote><pre> - * {@link #dropArguments(MethodHandle,int,List) dropArguments}(target, pos, Arrays.asList(valueTypes)) - * </pre></blockquote> - * @param target the method handle to invoke after the arguments are dropped - * @param valueTypes the type(s) of the argument(s) to drop - * @param pos position of first argument to drop (zero for the leftmost) - * @return a method handle which drops arguments of the given types, - * before calling the original method handle - * @throws NullPointerException if the target is null, - * or if the {@code valueTypes} array or any of its elements is null - * @throws IllegalArgumentException if any element of {@code valueTypes} is {@code void.class}, - * or if {@code pos} is negative or greater than the arity of the target, - * or if the new method handle's type would have too many parameters - */ - public static - MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) { - return dropArguments(target, pos, Arrays.asList(valueTypes)); - } - - /** - * Adapts a target method handle by pre-processing - * one or more of its arguments, each with its own unary filter function, - * and then calling the target with each pre-processed argument - * replaced by the result of its corresponding filter function. - * <p> - * The pre-processing is performed by one or more method handles, - * specified in the elements of the {@code filters} array. - * The first element of the filter array corresponds to the {@code pos} - * argument of the target, and so on in sequence. - * <p> - * Null arguments in the array are treated as identity functions, - * and the corresponding arguments left unchanged. - * (If there are no non-null elements in the array, the original target is returned.) - * Each filter is applied to the corresponding argument of the adapter. - * <p> - * If a filter {@code F} applies to the {@code N}th argument of - * the target, then {@code F} must be a method handle which - * takes exactly one argument. The type of {@code F}'s sole argument - * replaces the corresponding argument type of the target - * in the resulting adapted method handle. - * The return type of {@code F} must be identical to the corresponding - * parameter type of the target. - * <p> - * It is an error if there are elements of {@code filters} - * (null or not) - * which do not correspond to argument positions in the target. - * <b>Example:</b> - * <p><blockquote><pre> -import static java.lang.invoke.MethodHandles.*; -import static java.lang.invoke.MethodType.*; -... -MethodHandle cat = lookup().findVirtual(String.class, - "concat", methodType(String.class, String.class)); -MethodHandle upcase = lookup().findVirtual(String.class, - "toUpperCase", methodType(String.class)); -assertEquals("xy", (String) cat.invokeExact("x", "y")); -MethodHandle f0 = filterArguments(cat, 0, upcase); -assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy -MethodHandle f1 = filterArguments(cat, 1, upcase); -assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY -MethodHandle f2 = filterArguments(cat, 0, upcase, upcase); -assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY - * </pre></blockquote> - * <p> Here is pseudocode for the resulting adapter: - * <blockquote><pre> - * V target(P... p, A[i]... a[i], B... b); - * A[i] filter[i](V[i]); - * T adapter(P... p, V[i]... v[i], B... b) { - * return target(p..., f[i](v[i])..., b...); - * } - * </pre></blockquote> - * - * @param target the method handle to invoke after arguments are filtered - * @param pos the position of the first argument to filter - * @param filters method handles to call initially on filtered arguments - * @return method handle which incorporates the specified argument filtering logic - * @throws NullPointerException if the target is null - * or if the {@code filters} array is null - * @throws IllegalArgumentException if a non-null element of {@code filters} - * does not match a corresponding argument type of target as described above, - * or if the {@code pos+filters.length} is greater than {@code target.type().parameterCount()} - */ - public static - MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) { - MethodType targetType = target.type(); - MethodHandle adapter = target; - MethodType adapterType = null; - assert((adapterType = targetType) != null); - int maxPos = targetType.parameterCount(); - if (pos + filters.length > maxPos) - throw newIllegalArgumentException("too many filters"); - int curPos = pos-1; // pre-incremented - for (MethodHandle filter : filters) { - curPos += 1; - if (filter == null) continue; // ignore null elements of filters - adapter = filterArgument(adapter, curPos, filter); - assert((adapterType = adapterType.changeParameterType(curPos, filter.type().parameterType(0))) != null); - } - assert(adapterType.equals(adapter.type())); - return adapter; - } - - /*non-public*/ static - MethodHandle filterArgument(MethodHandle target, int pos, MethodHandle filter) { - MethodType targetType = target.type(); - MethodType filterType = filter.type(); - if (filterType.parameterCount() != 1 - || filterType.returnType() != targetType.parameterType(pos)) - throw newIllegalArgumentException("target and filter types do not match", targetType, filterType); - return MethodHandleImpl.filterArgument(target, pos, filter); - } - - /** - * Adapts a target method handle by post-processing - * its return value (if any) with a filter (another method handle). - * The result of the filter is returned from the adapter. - * <p> - * If the target returns a value, the filter must accept that value as - * its only argument. - * If the target returns void, the filter must accept no arguments. - * <p> - * The return type of the filter - * replaces the return type of the target - * in the resulting adapted method handle. - * The argument type of the filter (if any) must be identical to the - * return type of the target. - * <b>Example:</b> - * <p><blockquote><pre> -import static java.lang.invoke.MethodHandles.*; -import static java.lang.invoke.MethodType.*; -... -MethodHandle cat = lookup().findVirtual(String.class, - "concat", methodType(String.class, String.class)); -MethodHandle length = lookup().findVirtual(String.class, - "length", methodType(int.class)); -System.out.println((String) cat.invokeExact("x", "y")); // xy -MethodHandle f0 = filterReturnValue(cat, length); -System.out.println((int) f0.invokeExact("x", "y")); // 2 - * </pre></blockquote> - * <p> Here is pseudocode for the resulting adapter: - * <blockquote><pre> - * V target(A...); - * T filter(V); - * T adapter(A... a) { - * V v = target(a...); - * return filter(v); - * } - * // and if the target has a void return: - * void target2(A...); - * T filter2(); - * T adapter2(A... a) { - * target2(a...); - * return filter2(); - * } - * // and if the filter has a void return: - * V target3(A...); - * void filter3(V); - * void adapter3(A... a) { - * V v = target3(a...); - * filter3(v); - * } - * </pre></blockquote> - * @param target the method handle to invoke before filtering the return value - * @param filter method handle to call on the return value - * @return method handle which incorporates the specified return value filtering logic - * @throws NullPointerException if either argument is null - * @throws IllegalArgumentException if the argument list of {@code filter} - * does not match the return type of target as described above - */ - public static - MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) { - MethodType targetType = target.type(); - MethodType filterType = filter.type(); - Class<?> rtype = targetType.returnType(); - int filterValues = filterType.parameterCount(); - if (filterValues == 0 - ? (rtype != void.class) - : (rtype != filterType.parameterType(0))) - throw newIllegalArgumentException("target and filter types do not match", target, filter); - // result = fold( lambda(retval, arg...) { filter(retval) }, - // lambda( arg...) { target(arg...) } ) - MethodType newType = targetType.changeReturnType(filterType.returnType()); - MethodHandle result = null; - if (AdapterMethodHandle.canCollectArguments(filterType, targetType, 0, false)) { - result = AdapterMethodHandle.makeCollectArguments(filter, target, 0, false); - if (result != null) return result; - } - // FIXME: Too many nodes here. - assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this class is deprecated - MethodHandle returner = dropArguments(filter, filterValues, targetType.parameterList()); - result = foldArguments(returner, target); - assert(result.type().equals(newType)); - return result; - } - - /** - * Adapts a target method handle by pre-processing - * some of its arguments, and then calling the target with - * the result of the pre-processing, inserted into the original - * sequence of arguments. - * <p> - * The pre-processing is performed by {@code combiner}, a second method handle. - * Of the arguments passed to the adapter, the first {@code N} arguments - * are copied to the combiner, which is then called. - * (Here, {@code N} is defined as the parameter count of the combiner.) - * After this, control passes to the target, with any result - * from the combiner inserted before the original {@code N} incoming - * arguments. - * <p> - * If the combiner returns a value, the first parameter type of the target - * must be identical with the return type of the combiner, and the next - * {@code N} parameter types of the target must exactly match the parameters - * of the combiner. - * <p> - * If the combiner has a void return, no result will be inserted, - * and the first {@code N} parameter types of the target - * must exactly match the parameters of the combiner. - * <p> - * The resulting adapter is the same type as the target, except that the - * first parameter type is dropped, - * if it corresponds to the result of the combiner. - * <p> - * (Note that {@link #dropArguments(MethodHandle,int,List) dropArguments} can be used to remove any arguments - * that either the combiner or the target does not wish to receive. - * If some of the incoming arguments are destined only for the combiner, - * consider using {@link MethodHandle#asCollector asCollector} instead, since those - * arguments will not need to be live on the stack on entry to the - * target.) - * <b>Example:</b> - * <p><blockquote><pre> -import static java.lang.invoke.MethodHandles.*; -import static java.lang.invoke.MethodType.*; -... -MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class, - "println", methodType(void.class, String.class)) - .bindTo(System.out); -MethodHandle cat = lookup().findVirtual(String.class, - "concat", methodType(String.class, String.class)); -assertEquals("boojum", (String) cat.invokeExact("boo", "jum")); -MethodHandle catTrace = foldArguments(cat, trace); -// also prints "boo": -assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); - * </pre></blockquote> - * <p> Here is pseudocode for the resulting adapter: - * <blockquote><pre> - * // there are N arguments in A... - * T target(V, A[N]..., B...); - * V combiner(A...); - * T adapter(A... a, B... b) { - * V v = combiner(a...); - * return target(v, a..., b...); - * } - * // and if the combiner has a void return: - * T target2(A[N]..., B...); - * void combiner2(A...); - * T adapter2(A... a, B... b) { - * combiner2(a...); - * return target2(a..., b...); - * } - * </pre></blockquote> - * @param target the method handle to invoke after arguments are combined - * @param combiner method handle to call initially on the incoming arguments - * @return method handle which incorporates the specified argument folding logic - * @throws NullPointerException if either argument is null - * @throws IllegalArgumentException if {@code combiner}'s return type - * is non-void and not the same as the first argument type of - * the target, or if the initial {@code N} argument types - * of the target - * (skipping one matching the {@code combiner}'s return type) - * are not identical with the argument types of {@code combiner} - */ - public static - MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) { - int pos = 0; - MethodType targetType = target.type(); - MethodType combinerType = combiner.type(); - int foldPos = pos; - int foldArgs = combinerType.parameterCount(); - int foldVals = combinerType.returnType() == void.class ? 0 : 1; - int afterInsertPos = foldPos + foldVals; - boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs); - if (ok && !(combinerType.parameterList() - .equals(targetType.parameterList().subList(afterInsertPos, - afterInsertPos + foldArgs)))) - ok = false; - if (ok && foldVals != 0 && !combinerType.returnType().equals(targetType.parameterType(0))) - ok = false; - if (!ok) - throw misMatchedTypes("target and combiner types", targetType, combinerType); - MethodType newType = targetType.dropParameterTypes(foldPos, afterInsertPos); - MethodHandle res = MethodHandleImpl.foldArguments(target, newType, foldPos, combiner); - if (res == null) throw newIllegalArgumentException("cannot fold from "+newType+" to " +targetType); - return res; - } - - /** - * Makes a method handle which adapts a target method handle, - * by guarding it with a test, a boolean-valued method handle. - * If the guard fails, a fallback handle is called instead. - * All three method handles must have the same corresponding - * argument and return types, except that the return type - * of the test must be boolean, and the test is allowed - * to have fewer arguments than the other two method handles. - * <p> Here is pseudocode for the resulting adapter: - * <blockquote><pre> - * boolean test(A...); - * T target(A...,B...); - * T fallback(A...,B...); - * T adapter(A... a,B... b) { - * if (test(a...)) - * return target(a..., b...); - * else - * return fallback(a..., b...); - * } - * </pre></blockquote> - * Note that the test arguments ({@code a...} in the pseudocode) cannot - * be modified by execution of the test, and so are passed unchanged - * from the caller to the target or fallback as appropriate. - * @param test method handle used for test, must return boolean - * @param target method handle to call if test passes - * @param fallback method handle to call if test fails - * @return method handle which incorporates the specified if/then/else logic - * @throws NullPointerException if any argument is null - * @throws IllegalArgumentException if {@code test} does not return boolean, - * or if all three method types do not match (with the return - * type of {@code test} changed to match that of the target). - */ - public static - MethodHandle guardWithTest(MethodHandle test, - MethodHandle target, - MethodHandle fallback) { - MethodType gtype = test.type(); - MethodType ttype = target.type(); - MethodType ftype = fallback.type(); - if (!ttype.equals(ftype)) - throw misMatchedTypes("target and fallback types", ttype, ftype); - if (gtype.returnType() != boolean.class) - throw newIllegalArgumentException("guard type is not a predicate "+gtype); - List<Class<?>> targs = ttype.parameterList(); - List<Class<?>> gargs = gtype.parameterList(); - if (!targs.equals(gargs)) { - int gpc = gargs.size(), tpc = targs.size(); - if (gpc >= tpc || !targs.subList(0, gpc).equals(gargs)) - throw misMatchedTypes("target and test types", ttype, gtype); - test = dropArguments(test, gpc, targs.subList(gpc, tpc)); - gtype = test.type(); - } - return MethodHandleImpl.makeGuardWithTest(test, target, fallback); - } - - static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) { - return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2); - } - - /** - * Makes a method handle which adapts a target method handle, - * by running it inside an exception handler. - * If the target returns normally, the adapter returns that value. - * If an exception matching the specified type is thrown, the fallback - * handle is called instead on the exception, plus the original arguments. - * <p> - * The target and handler must have the same corresponding - * argument and return types, except that handler may omit trailing arguments - * (similarly to the predicate in {@link #guardWithTest guardWithTest}). - * Also, the handler must have an extra leading parameter of {@code exType} or a supertype. - * <p> Here is pseudocode for the resulting adapter: - * <blockquote><pre> - * T target(A..., B...); - * T handler(ExType, A...); - * T adapter(A... a, B... b) { - * try { - * return target(a..., b...); - * } catch (ExType ex) { - * return handler(ex, a...); - * } - * } - * </pre></blockquote> - * Note that the saved arguments ({@code a...} in the pseudocode) cannot - * be modified by execution of the target, and so are passed unchanged - * from the caller to the handler, if the handler is invoked. - * <p> - * The target and handler must return the same type, even if the handler - * always throws. (This might happen, for instance, because the handler - * is simulating a {@code finally} clause). - * To create such a throwing handler, compose the handler creation logic - * with {@link #throwException throwException}, - * in order to create a method handle of the correct return type. - * @param target method handle to call - * @param exType the type of exception which the handler will catch - * @param handler method handle to call if a matching exception is thrown - * @return method handle which incorporates the specified try/catch logic - * @throws NullPointerException if any argument is null - * @throws IllegalArgumentException if {@code handler} does not accept - * the given exception type, or if the method handle types do - * not match in their return types and their - * corresponding parameters - */ - public static - MethodHandle catchException(MethodHandle target, - Class<? extends Throwable> exType, - MethodHandle handler) { - MethodType ttype = target.type(); - MethodType htype = handler.type(); - if (htype.parameterCount() < 1 || - !htype.parameterType(0).isAssignableFrom(exType)) - throw newIllegalArgumentException("handler does not accept exception type "+exType); - if (htype.returnType() != ttype.returnType()) - throw misMatchedTypes("target and handler return types", ttype, htype); - List<Class<?>> targs = ttype.parameterList(); - List<Class<?>> hargs = htype.parameterList(); - hargs = hargs.subList(1, hargs.size()); // omit leading parameter from handler - if (!targs.equals(hargs)) { - int hpc = hargs.size(), tpc = targs.size(); - if (hpc >= tpc || !targs.subList(0, hpc).equals(hargs)) - throw misMatchedTypes("target and handler types", ttype, htype); - handler = dropArguments(handler, 1+hpc, targs.subList(hpc, tpc)); - htype = handler.type(); - } - return MethodHandleImpl.makeGuardWithCatch(target, exType, handler); - } - - /** - * Produces a method handle which will throw exceptions of the given {@code exType}. - * The method handle will accept a single argument of {@code exType}, - * and immediately throw it as an exception. - * The method type will nominally specify a return of {@code returnType}. - * The return type may be anything convenient: It doesn't matter to the - * method handle's behavior, since it will never return normally. - * @return method handle which can throw the given exceptions - * @throws NullPointerException if either argument is null - */ - public static - MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) { - return MethodHandleImpl.throwException(MethodType.methodType(returnType, exType)); - } -} diff --git a/openjdk/java/lang/invoke/MutableCallSite.java b/openjdk/java/lang/invoke/MutableCallSite.java deleted file mode 100644 index d48f99af..00000000 --- a/openjdk/java/lang/invoke/MutableCallSite.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang.invoke; - -import java.util.concurrent.atomic.AtomicInteger; - -/** - * A {@code MutableCallSite} is a {@link CallSite} whose target variable - * behaves like an ordinary field. - * An {@code invokedynamic} instruction linked to a {@code MutableCallSite} delegates - * all calls to the site's current target. - * The {@linkplain CallSite#dynamicInvoker dynamic invoker} of a mutable call site - * also delegates each call to the site's current target. - * <p> - * Here is an example of a mutable call site which introduces a - * state variable into a method handle chain. - * <!-- JavaDocExamplesTest.testMutableCallSite --> - * <blockquote><pre> -MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class)); -MethodHandle MH_name = name.dynamicInvoker(); -MethodType MT_str1 = MethodType.methodType(String.class); -MethodHandle MH_upcase = MethodHandles.lookup() - .findVirtual(String.class, "toUpperCase", MT_str1); -MethodHandle worker1 = MethodHandles.filterReturnValue(MH_name, MH_upcase); -name.setTarget(MethodHandles.constant(String.class, "Rocky")); -assertEquals("ROCKY", (String) worker1.invokeExact()); -name.setTarget(MethodHandles.constant(String.class, "Fred")); -assertEquals("FRED", (String) worker1.invokeExact()); -// (mutation can be continued indefinitely) - * </pre></blockquote> - * <p> - * The same call site may be used in several places at once. - * <blockquote><pre> -MethodType MT_str2 = MethodType.methodType(String.class, String.class); -MethodHandle MH_cat = lookup().findVirtual(String.class, - "concat", methodType(String.class, String.class)); -MethodHandle MH_dear = MethodHandles.insertArguments(MH_cat, 1, ", dear?"); -MethodHandle worker2 = MethodHandles.filterReturnValue(MH_name, MH_dear); -assertEquals("Fred, dear?", (String) worker2.invokeExact()); -name.setTarget(MethodHandles.constant(String.class, "Wilma")); -assertEquals("WILMA", (String) worker1.invokeExact()); -assertEquals("Wilma, dear?", (String) worker2.invokeExact()); - * </pre></blockquote> - * <p> - * <em>Non-synchronization of target values:</em> - * A write to a mutable call site's target does not force other threads - * to become aware of the updated value. Threads which do not perform - * suitable synchronization actions relative to the updated call site - * may cache the old target value and delay their use of the new target - * value indefinitely. - * (This is a normal consequence of the Java Memory Model as applied - * to object fields.) - * <p> - * The {@link #syncAll syncAll} operation provides a way to force threads - * to accept a new target value, even if there is no other synchronization. - * <p> - * For target values which will be frequently updated, consider using - * a {@linkplain VolatileCallSite volatile call site} instead. - * @author John Rose, JSR 292 EG - */ -public class MutableCallSite extends CallSite { - /** - * Creates a blank call site object with the given method type. - * The initial target is set to a method handle of the given type - * which will throw an {@link IllegalStateException} if called. - * <p> - * The type of the call site is permanently set to the given type. - * <p> - * Before this {@code CallSite} object is returned from a bootstrap method, - * or invoked in some other manner, - * it is usually provided with a more useful target method, - * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}. - * @param type the method type that this call site will have - * @throws NullPointerException if the proposed type is null - */ - public MutableCallSite(MethodType type) { - super(type); - } - - /** - * Creates a call site object with an initial target method handle. - * The type of the call site is permanently set to the initial target's type. - * @param target the method handle that will be the initial target of the call site - * @throws NullPointerException if the proposed target is null - */ - public MutableCallSite(MethodHandle target) { - super(target); - } - - /** - * Returns the target method of the call site, which behaves - * like a normal field of the {@code MutableCallSite}. - * <p> - * The interactions of {@code getTarget} with memory are the same - * as of a read from an ordinary variable, such as an array element or a - * non-volatile, non-final field. - * <p> - * In particular, the current thread may choose to reuse the result - * of a previous read of the target from memory, and may fail to see - * a recent update to the target by another thread. - * - * @return the linkage state of this call site, a method handle which can change over time - * @see #setTarget - */ - @Override public final MethodHandle getTarget() { - return target; - } - - /** - * Updates the target method of this call site, as a normal variable. - * The type of the new target must agree with the type of the old target. - * <p> - * The interactions with memory are the same - * as of a write to an ordinary variable, such as an array element or a - * non-volatile, non-final field. - * <p> - * In particular, unrelated threads may fail to see the updated target - * until they perform a read from memory. - * Stronger guarantees can be created by putting appropriate operations - * into the bootstrap method and/or the target methods used - * at any given call site. - * - * @param newTarget the new target - * @throws NullPointerException if the proposed new target is null - * @throws WrongMethodTypeException if the proposed new target - * has a method type that differs from the previous target - * @see #getTarget - */ - @Override public void setTarget(MethodHandle newTarget) { - checkTargetChange(this.target, newTarget); - setTargetNormal(newTarget); - } - - /** - * {@inheritDoc} - */ - @Override - public final MethodHandle dynamicInvoker() { - return makeDynamicInvoker(); - } - - /** - * Performs a synchronization operation on each call site in the given array, - * forcing all other threads to throw away any cached values previously - * loaded from the target of any of the call sites. - * <p> - * This operation does not reverse any calls that have already started - * on an old target value. - * (Java supports {@linkplain java.lang.Object#wait() forward time travel} only.) - * <p> - * The overall effect is to force all future readers of each call site's target - * to accept the most recently stored value. - * ("Most recently" is reckoned relative to the {@code syncAll} itself.) - * Conversely, the {@code syncAll} call may block until all readers have - * (somehow) decached all previous versions of each call site's target. - * <p> - * To avoid race conditions, calls to {@code setTarget} and {@code syncAll} - * should generally be performed under some sort of mutual exclusion. - * Note that reader threads may observe an updated target as early - * as the {@code setTarget} call that install the value - * (and before the {@code syncAll} that confirms the value). - * On the other hand, reader threads may observe previous versions of - * the target until the {@code syncAll} call returns - * (and after the {@code setTarget} that attempts to convey the updated version). - * <p> - * This operation is likely to be expensive and should be used sparingly. - * If possible, it should be buffered for batch processing on sets of call sites. - * <p> - * If {@code sites} contains a null element, - * a {@code NullPointerException} will be raised. - * In this case, some non-null elements in the array may be - * processed before the method returns abnormally. - * Which elements these are (if any) is implementation-dependent. - * - * <h3>Java Memory Model details</h3> - * In terms of the Java Memory Model, this operation performs a synchronization - * action which is comparable in effect to the writing of a volatile variable - * by the current thread, and an eventual volatile read by every other thread - * that may access one of the affected call sites. - * <p> - * The following effects are apparent, for each individual call site {@code S}: - * <ul> - * <li>A new volatile variable {@code V} is created, and written by the current thread. - * As defined by the JMM, this write is a global synchronization event. - * <li>As is normal with thread-local ordering of write events, - * every action already performed by the current thread is - * taken to happen before the volatile write to {@code V}. - * (In some implementations, this means that the current thread - * performs a global release operation.) - * <li>Specifically, the write to the current target of {@code S} is - * taken to happen before the volatile write to {@code V}. - * <li>The volatile write to {@code V} is placed - * (in an implementation specific manner) - * in the global synchronization order. - * <li>Consider an arbitrary thread {@code T} (other than the current thread). - * If {@code T} executes a synchronization action {@code A} - * after the volatile write to {@code V} (in the global synchronization order), - * it is therefore required to see either the current target - * of {@code S}, or a later write to that target, - * if it executes a read on the target of {@code S}. - * (This constraint is called "synchronization-order consistency".) - * <li>The JMM specifically allows optimizing compilers to elide - * reads or writes of variables that are known to be useless. - * Such elided reads and writes have no effect on the happens-before - * relation. Regardless of this fact, the volatile {@code V} - * will not be elided, even though its written value is - * indeterminate and its read value is not used. - * </ul> - * Because of the last point, the implementation behaves as if a - * volatile read of {@code V} were performed by {@code T} - * immediately after its action {@code A}. In the local ordering - * of actions in {@code T}, this read happens before any future - * read of the target of {@code S}. It is as if the - * implementation arbitrarily picked a read of {@code S}'s target - * by {@code T}, and forced a read of {@code V} to precede it, - * thereby ensuring communication of the new target value. - * <p> - * As long as the constraints of the Java Memory Model are obeyed, - * implementations may delay the completion of a {@code syncAll} - * operation while other threads ({@code T} above) continue to - * use previous values of {@code S}'s target. - * However, implementations are (as always) encouraged to avoid - * livelock, and to eventually require all threads to take account - * of the updated target. - * - * <p style="font-size:smaller;"> - * <em>Discussion:</em> - * For performance reasons, {@code syncAll} is not a virtual method - * on a single call site, but rather applies to a set of call sites. - * Some implementations may incur a large fixed overhead cost - * for processing one or more synchronization operations, - * but a small incremental cost for each additional call site. - * In any case, this operation is likely to be costly, since - * other threads may have to be somehow interrupted - * in order to make them notice the updated target value. - * However, it may be observed that a single call to synchronize - * several sites has the same formal effect as many calls, - * each on just one of the sites. - * - * <p style="font-size:smaller;"> - * <em>Implementation Note:</em> - * Simple implementations of {@code MutableCallSite} may use - * a volatile variable for the target of a mutable call site. - * In such an implementation, the {@code syncAll} method can be a no-op, - * and yet it will conform to the JMM behavior documented above. - * - * @param sites an array of call sites to be synchronized - * @throws NullPointerException if the {@code sites} array reference is null - * or the array contains a null - */ - public static void syncAll(MutableCallSite[] sites) { - if (sites.length == 0) return; - STORE_BARRIER.lazySet(0); - for (int i = 0; i < sites.length; i++) { - sites[i].getClass(); // trigger NPE on first null - } - // FIXME: NYI - } - private static final AtomicInteger STORE_BARRIER = new AtomicInteger(); -} diff --git a/openjdk/java/lang/invoke/VolatileCallSite.java b/openjdk/java/lang/invoke/VolatileCallSite.java deleted file mode 100644 index de88f36b..00000000 --- a/openjdk/java/lang/invoke/VolatileCallSite.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang.invoke; - -/** - * A {@code VolatileCallSite} is a {@link CallSite} whose target acts like a volatile variable. - * An {@code invokedynamic} instruction linked to a {@code VolatileCallSite} sees updates - * to its call site target immediately, even if the update occurs in another thread. - * There may be a performance penalty for such tight coupling between threads. - * <p> - * Unlike {@code MutableCallSite}, there is no - * {@linkplain MutableCallSite#syncAll syncAll operation} on volatile - * call sites, since every write to a volatile variable is implicitly - * synchronized with reader threads. - * <p> - * In other respects, a {@code VolatileCallSite} is interchangeable - * with {@code MutableCallSite}. - * @see MutableCallSite - * @author John Rose, JSR 292 EG - */ -public class VolatileCallSite extends CallSite { - /** - * Creates a call site with a volatile binding to its target. - * The initial target is set to a method handle - * of the given type which will throw an {@code IllegalStateException} if called. - * @param type the method type that this call site will have - * @throws NullPointerException if the proposed type is null - */ - public VolatileCallSite(MethodType type) { - super(type); - } - - /** - * Creates a call site with a volatile binding to its target. - * The target is set to the given value. - * @param target the method handle that will be the initial target of the call site - * @throws NullPointerException if the proposed target is null - */ - public VolatileCallSite(MethodHandle target) { - super(target); - } - - /** - * Returns the target method of the call site, which behaves - * like a {@code volatile} field of the {@code VolatileCallSite}. - * <p> - * The interactions of {@code getTarget} with memory are the same - * as of a read from a {@code volatile} field. - * <p> - * In particular, the current thread is required to issue a fresh - * read of the target from memory, and must not fail to see - * a recent update to the target by another thread. - * - * @return the linkage state of this call site, a method handle which can change over time - * @see #setTarget - */ - @Override public final MethodHandle getTarget() { - return getTargetVolatile(); - } - - /** - * Updates the target method of this call site, as a volatile variable. - * The type of the new target must agree with the type of the old target. - * <p> - * The interactions with memory are the same as of a write to a volatile field. - * In particular, any threads is guaranteed to see the updated target - * the next time it calls {@code getTarget}. - * @param newTarget the new target - * @throws NullPointerException if the proposed new target is null - * @throws WrongMethodTypeException if the proposed new target - * has a method type that differs from the previous target - * @see #getTarget - */ - @Override public void setTarget(MethodHandle newTarget) { - checkTargetChange(getTargetVolatile(), newTarget); - setTargetVolatile(newTarget); - } - - /** - * {@inheritDoc} - */ - @Override - public final MethodHandle dynamicInvoker() { - return makeDynamicInvoker(); - } -} diff --git a/openjdk/java/lang/management/PlatformComponent.java b/openjdk/java/lang/management/PlatformComponent.java deleted file mode 100644 index 3d29a16b..00000000 --- a/openjdk/java/lang/management/PlatformComponent.java +++ /dev/null @@ -1,407 +0,0 @@ -/* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang.management; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.HashSet; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import javax.management.MBeanServerConnection; -import javax.management.ObjectName; - -import sun.management.ManagementFactoryHelper; -import sun.management.Util; - -/** - * This enum class defines the list of platform components - * that provides monitoring and management support. - * Each enum represents one MXBean interface. A MXBean - * instance could implement one or more MXBean interfaces. - * - * For example, com.sun.management.GarbageCollectorMXBean - * extends java.lang.management.GarbageCollectorMXBean - * and there is one set of garbage collection MXBean instances, - * each of which implements both c.s.m. and j.l.m. interfaces. - * There are two separate enums GARBAGE_COLLECTOR - * and SUN_GARBAGE_COLLECTOR so that ManagementFactory.getPlatformMXBeans(Class) - * will return the list of MXBeans of the specified type. - * - * To add a new MXBean interface for the Java platform, - * add a new enum constant and implement the MXBeanFetcher. - */ -enum PlatformComponent { - - /** - * Class loading system of the Java virtual machine. - */ - CLASS_LOADING( - "java.lang.management.ClassLoadingMXBean", - "java.lang", "ClassLoading", defaultKeyProperties(), - true, // singleton - new MXBeanFetcher<ClassLoadingMXBean>() { - public List<ClassLoadingMXBean> getMXBeans() { - return Collections.singletonList(ManagementFactoryHelper.getClassLoadingMXBean()); - } - }), - - /** - * Compilation system of the Java virtual machine. - */ - COMPILATION( - "java.lang.management.CompilationMXBean", - "java.lang", "Compilation", defaultKeyProperties(), - true, // singleton - new MXBeanFetcher<CompilationMXBean>() { - public List<CompilationMXBean> getMXBeans() { - CompilationMXBean m = ManagementFactoryHelper.getCompilationMXBean(); - if (m == null) { - return Collections.emptyList(); - } else { - return Collections.singletonList(m); - } - } - }), - - /** - * Memory system of the Java virtual machine. - */ - MEMORY( - "java.lang.management.MemoryMXBean", - "java.lang", "Memory", defaultKeyProperties(), - true, // singleton - new MXBeanFetcher<MemoryMXBean>() { - public List<MemoryMXBean> getMXBeans() { - return Collections.singletonList(ManagementFactoryHelper.getMemoryMXBean()); - } - }), - - /** - * Garbage Collector in the Java virtual machine. - */ - GARBAGE_COLLECTOR( - "java.lang.management.GarbageCollectorMXBean", - "java.lang", "GarbageCollector", keyProperties("name"), - false, // zero or more instances - new MXBeanFetcher<GarbageCollectorMXBean>() { - public List<GarbageCollectorMXBean> getMXBeans() { - return ManagementFactoryHelper. - getGarbageCollectorMXBeans(); - } - }), - - /** - * Memory manager in the Java virtual machine. - */ - MEMORY_MANAGER( - "java.lang.management.MemoryManagerMXBean", - "java.lang", "MemoryManager", keyProperties("name"), - false, // zero or more instances - new MXBeanFetcher<MemoryManagerMXBean>() { - public List<MemoryManagerMXBean> getMXBeans() { - return ManagementFactoryHelper.getMemoryManagerMXBeans(); - } - }, - GARBAGE_COLLECTOR), - - /** - * Memory pool in the Java virtual machine. - */ - MEMORY_POOL( - "java.lang.management.MemoryPoolMXBean", - "java.lang", "MemoryPool", keyProperties("name"), - false, // zero or more instances - new MXBeanFetcher<MemoryPoolMXBean>() { - public List<MemoryPoolMXBean> getMXBeans() { - return ManagementFactoryHelper.getMemoryPoolMXBeans(); - } - }), - - /** - * Operating system on which the Java virtual machine is running - */ - OPERATING_SYSTEM( - "java.lang.management.OperatingSystemMXBean", - "java.lang", "OperatingSystem", defaultKeyProperties(), - true, // singleton - new MXBeanFetcher<OperatingSystemMXBean>() { - public List<OperatingSystemMXBean> getMXBeans() { - return Collections.singletonList(ManagementFactoryHelper.getOperatingSystemMXBean()); - } - }), - - /** - * Runtime system of the Java virtual machine. - */ - RUNTIME( - "java.lang.management.RuntimeMXBean", - "java.lang", "Runtime", defaultKeyProperties(), - true, // singleton - new MXBeanFetcher<RuntimeMXBean>() { - public List<RuntimeMXBean> getMXBeans() { - return Collections.singletonList(ManagementFactoryHelper.getRuntimeMXBean()); - } - }), - - /** - * Threading system of the Java virtual machine. - */ - THREADING( - "java.lang.management.ThreadMXBean", - "java.lang", "Threading", defaultKeyProperties(), - true, // singleton - new MXBeanFetcher<ThreadMXBean>() { - public List<ThreadMXBean> getMXBeans() { - return Collections.singletonList(ManagementFactoryHelper.getThreadMXBean()); - } - }), - - - /** - * Logging facility. - */ - LOGGING( - "java.lang.management.PlatformLoggingMXBean", - "java.util.logging", "Logging", defaultKeyProperties(), - true, // singleton - new MXBeanFetcher<PlatformLoggingMXBean>() { - public List<PlatformLoggingMXBean> getMXBeans() { - PlatformLoggingMXBean m = ManagementFactoryHelper.getPlatformLoggingMXBean(); - if (m == null) { - return Collections.emptyList(); - } else { - return Collections.singletonList(m); - } - } - }), - - /** - * Buffer pools. - */ - BUFFER_POOL( - "java.lang.management.BufferPoolMXBean", - "java.nio", "BufferPool", keyProperties("name"), - false, // zero or more instances - new MXBeanFetcher<BufferPoolMXBean>() { - public List<BufferPoolMXBean> getMXBeans() { - return ManagementFactoryHelper.getBufferPoolMXBeans(); - } - }); - - /** - * A task that returns the MXBeans for a component. - */ - interface MXBeanFetcher<T extends PlatformManagedObject> { - public List<T> getMXBeans(); - } - - /* - * Returns a list of the GC MXBeans of the given type. - */ - private static <T extends GarbageCollectorMXBean> - List<T> getGcMXBeanList(Class<T> gcMXBeanIntf) { - List<GarbageCollectorMXBean> list = - ManagementFactoryHelper.getGarbageCollectorMXBeans(); - List<T> result = new ArrayList<>(list.size()); - for (GarbageCollectorMXBean m : list) { - if (gcMXBeanIntf.isInstance(m)) { - result.add(gcMXBeanIntf.cast(m)); - } - } - return result; - } - - /* - * Returns the OS mxbean instance of the given type. - */ - private static <T extends OperatingSystemMXBean> - List<T> getOSMXBeanList(Class<T> osMXBeanIntf) { - OperatingSystemMXBean m = - ManagementFactoryHelper.getOperatingSystemMXBean(); - if (osMXBeanIntf.isInstance(m)) { - return Collections.singletonList(osMXBeanIntf.cast(m)); - } else { - return Collections.emptyList(); - } - } - - private final String mxbeanInterfaceName; - private final String domain; - private final String type; - private final Set<String> keyProperties; - private final MXBeanFetcher fetcher; - private final PlatformComponent[] subComponents; - private final boolean singleton; - - private PlatformComponent(String intfName, - String domain, String type, - Set<String> keyProperties, - boolean singleton, - MXBeanFetcher fetcher, - PlatformComponent... subComponents) { - this.mxbeanInterfaceName = intfName; - this.domain = domain; - this.type = type; - this.keyProperties = keyProperties; - this.singleton = singleton; - this.fetcher = fetcher; - this.subComponents = subComponents; - } - - private static Set<String> defaultKeyProps; - private static Set<String> defaultKeyProperties() { - if (defaultKeyProps == null) { - defaultKeyProps = Collections.singleton("type"); - } - return defaultKeyProps; - } - - private static Set<String> keyProperties(String... keyNames) { - Set<String> set = new HashSet<>(); - set.add("type"); - for (String s : keyNames) { - set.add(s); - } - return set; - } - - boolean isSingleton() { - return singleton; - } - - String getMXBeanInterfaceName() { - return mxbeanInterfaceName; - } - - @SuppressWarnings("unchecked") - Class<? extends PlatformManagedObject> getMXBeanInterface() { - try { - // Lazy loading the MXBean interface only when it is needed - return (Class<? extends PlatformManagedObject>) - Class.forName(mxbeanInterfaceName, false, null); - } catch (ClassNotFoundException x) { - throw new AssertionError(x); - } - } - - @SuppressWarnings("unchecked") - <T extends PlatformManagedObject> - List<T> getMXBeans(Class<T> mxbeanInterface) - { - return fetcher.getMXBeans(); - } - - <T extends PlatformManagedObject> T getSingletonMXBean(Class<T> mxbeanInterface) - { - if (!singleton) - throw new IllegalArgumentException(mxbeanInterfaceName + - " can have zero or more than one instances"); - - List<T> list = fetcher.getMXBeans(); - assert list.size() == 1; - return list.isEmpty() ? null : list.get(0); - } - - <T extends PlatformManagedObject> - T getSingletonMXBean(MBeanServerConnection mbs, Class<T> mxbeanInterface) - throws java.io.IOException - { - if (!singleton) - throw new IllegalArgumentException(mxbeanInterfaceName + - " can have zero or more than one instances"); - - // ObjectName of a singleton MXBean contains only domain and type - assert keyProperties.size() == 1; - String on = domain + ":type=" + type; - return ManagementFactory.newPlatformMXBeanProxy(mbs, - on, - mxbeanInterface); - } - - <T extends PlatformManagedObject> - List<T> getMXBeans(MBeanServerConnection mbs, Class<T> mxbeanInterface) - throws java.io.IOException - { - List<T> result = new ArrayList<>(); - for (ObjectName on : getObjectNames(mbs)) { - result.add(ManagementFactory. - newPlatformMXBeanProxy(mbs, - on.getCanonicalName(), - mxbeanInterface) - ); - } - return result; - } - - private Set<ObjectName> getObjectNames(MBeanServerConnection mbs) - throws java.io.IOException - { - String domainAndType = domain + ":type=" + type; - if (keyProperties.size() > 1) { - // if there are more than 1 key properties (i.e. other than "type") - domainAndType += ",*"; - } - ObjectName on = Util.newObjectName(domainAndType); - Set<ObjectName> set = mbs.queryNames(on, null); - for (PlatformComponent pc : subComponents) { - set.addAll(pc.getObjectNames(mbs)); - } - return set; - } - - // a map from MXBean interface name to PlatformComponent - private static Map<String, PlatformComponent> enumMap; - private static synchronized void ensureInitialized() { - if (enumMap == null) { - enumMap = new HashMap<>(); - for (PlatformComponent pc: PlatformComponent.values()) { - // Use String as the key rather than Class<?> to avoid - // causing unnecessary class loading of management interface - enumMap.put(pc.getMXBeanInterfaceName(), pc); - } - } - } - - static boolean isPlatformMXBean(String cn) { - ensureInitialized(); - return enumMap.containsKey(cn); - } - - static <T extends PlatformManagedObject> - PlatformComponent getPlatformComponent(Class<T> mxbeanInterface) - { - ensureInitialized(); - String cn = mxbeanInterface.getName(); - PlatformComponent pc = enumMap.get(cn); - if (pc != null && pc.getMXBeanInterface() == mxbeanInterface) - return pc; - return null; - } - - private static final long serialVersionUID = 6992337162326171013L; -} diff --git a/openjdk/java/lang/ref/Reference.java b/openjdk/java/lang/ref/Reference.java deleted file mode 100644 index cc2bfa5c..00000000 --- a/openjdk/java/lang/ref/Reference.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - Copyright (C) 2003-2012 Jeroen Frijters - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jeroen Frijters - jeroen@frijters.net - -*/ -package java.lang.ref; - -import cli.System.Collections.Hashtable; -import sun.misc.Cleaner; - -public abstract class Reference<T> -{ - // accessed by inner class - volatile cli.System.WeakReference weakRef; - volatile T strongRef; - volatile ReferenceQueue<? super T> queue; - volatile Reference next; - - private static native boolean noclassgc(); - - Reference(T referent) - { - this(referent, null); - } - - Reference(T referent, ReferenceQueue<? super T> queue) - { - this.queue = queue == null ? ReferenceQueue.NULL : queue; - if (referent != null) - { - if (referent instanceof Class && noclassgc()) - { - // We don't do Class gc, so no point in using a weak reference for classes. - strongRef = referent; - } - else - { - weakRef = new cli.System.WeakReference(referent, this instanceof PhantomReference); - if (queue != null || referent instanceof Cleaner || this instanceof SoftReference) - { - new QueueWatcher(this); - } - } - } - } - - private static final boolean debug = false; - - private static final class QueueWatcher - { - private static final Hashtable keepAlive = Hashtable.Synchronized(new Hashtable()); - private cli.System.WeakReference handle; - - QueueWatcher(Reference r) - { - handle = new cli.System.WeakReference(r, true); - // FXBUG when a WeakReference is finalizer reachable, it gets cleared by the GC (even if we call GC.SuppressFinalize), - // so we have to maintain a strong reference to it to prevent it from being cleared. - keepAlive.Add(handle, null); - } - - boolean check(Reference r) - { - r.strongRef = null; - boolean alive = false; - try - { - if (false) throw new cli.System.InvalidOperationException(); - cli.System.WeakReference referent = r.weakRef; - if (referent == null) - { - // ref was explicitly cleared, so we don't enqueue - return false; - } - alive = referent.get_IsAlive(); - } - catch (cli.System.InvalidOperationException x) - { - // this happens if the reference is already finalized (if we were - // the only one still hanging on to it) - } - if (alive) - { - // we don't want to keep creating finalizable objects during shutdown - if (!cli.System.Environment.get_HasShutdownStarted()) - { - return true; - } - } - else - { - if (r instanceof Cleaner) - { - ((Cleaner)r).clean(); - } - else if (r.queue != null) - { - r.queue.enqueue(r); - } - } - return false; - } - - protected void finalize() - { - Reference r = (Reference)handle.get_Target(); - if (debug) - cli.System.Console.WriteLine("~QueueWatcher: " + hashCode() + " on " + r); - if (r != null && r.next == null && check(r)) - { - cli.System.GC.ReRegisterForFinalize(QueueWatcher.this); - } - else - { - handle.set_Target(null); - keepAlive.Remove(handle); - } - } - } - - public T get() - { - try - { - if (false) throw new cli.System.InvalidOperationException(); - cli.System.WeakReference referent = this.weakRef; - if (referent == null) - { - return strongRef; - } - T value = (T)referent.get_Target(); - if (value == null) - { - queue.enqueue(this); - } - return value; - } - catch (cli.System.InvalidOperationException x) - { - // we were already finalized, so we just return null. - return null; - } - } - - public void clear() - { - weakRef = null; - strongRef = null; - } - - public synchronized boolean isEnqueued() - { - return queue != ReferenceQueue.NULL && next != null; - } - - public boolean enqueue() - { - return queue.enqueue(this); - } -} diff --git a/openjdk/java/lang/ref/SoftReference.java b/openjdk/java/lang/ref/SoftReference.java deleted file mode 100644 index 04d24933..00000000 --- a/openjdk/java/lang/ref/SoftReference.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 1997, 2003, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang.ref; - - -/** - * Soft reference objects, which are cleared at the discretion of the garbage - * collector in response to memory demand. Soft references are most often used - * to implement memory-sensitive caches. - * - * <p> Suppose that the garbage collector determines at a certain point in time - * that an object is <a href="package-summary.html#reachability">softly - * reachable</a>. At that time it may choose to clear atomically all soft - * references to that object and all soft references to any other - * softly-reachable objects from which that object is reachable through a chain - * of strong references. At the same time or at some later time it will - * enqueue those newly-cleared soft references that are registered with - * reference queues. - * - * <p> All soft references to softly-reachable objects are guaranteed to have - * been cleared before the virtual machine throws an - * <code>OutOfMemoryError</code>. Otherwise no constraints are placed upon the - * time at which a soft reference will be cleared or the order in which a set - * of such references to different objects will be cleared. Virtual machine - * implementations are, however, encouraged to bias against clearing - * recently-created or recently-used soft references. - * - * <p> Direct instances of this class may be used to implement simple caches; - * this class or derived subclasses may also be used in larger data structures - * to implement more sophisticated caches. As long as the referent of a soft - * reference is strongly reachable, that is, is actually in use, the soft - * reference will not be cleared. Thus a sophisticated cache can, for example, - * prevent its most recently used entries from being discarded by keeping - * strong referents to those entries, leaving the remaining entries to be - * discarded at the discretion of the garbage collector. - * - * @author Mark Reinhold - * @since 1.2 - */ - -public class SoftReference<T> extends Reference<T> { - - /** - * Timestamp clock, updated by the garbage collector - */ - static private long clock; - - /** - * Timestamp updated by each invocation of the get method. The VM may use - * this field when selecting soft references to be cleared, but it is not - * required to do so. - */ - private long timestamp; - - /** - * Creates a new soft reference that refers to the given object. The new - * reference is not registered with any queue. - * - * @param referent object the new soft reference will refer to - */ - public SoftReference(T referent) { - super(referent); - strongRef = referent; - } - - /** - * Creates a new soft reference that refers to the given object and is - * registered with the given queue. - * - * @param referent object the new soft reference will refer to - * @param q the queue with which the reference is to be registered, - * or <tt>null</tt> if registration is not required - * - */ - public SoftReference(T referent, ReferenceQueue<? super T> q) { - super(referent, q); - strongRef = referent; - } - - /** - * Returns this reference object's referent. If this reference object has - * been cleared, either by the program or by the garbage collector, then - * this method returns <code>null</code>. - * - * @return The object to which this reference refers, or - * <code>null</code> if this reference object has been cleared - */ - public T get() { - T o = super.get(); - strongRef = o; - return o; - } - -} diff --git a/openjdk/java/lang/reflect/Constructor.java b/openjdk/java/lang/reflect/Constructor.java deleted file mode 100644 index b13d30a5..00000000 --- a/openjdk/java/lang/reflect/Constructor.java +++ /dev/null @@ -1,674 +0,0 @@ -/* - * Copyright (c) 1996, 2010, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang.reflect; - -import sun.reflect.CallerSensitive; -import sun.reflect.ConstructorAccessor; -import sun.reflect.Reflection; -import sun.reflect.generics.repository.ConstructorRepository; -import sun.reflect.generics.factory.CoreReflectionFactory; -import sun.reflect.generics.factory.GenericsFactory; -import sun.reflect.generics.scope.ConstructorScope; -import java.lang.annotation.Annotation; -import java.util.Map; -import sun.reflect.annotation.AnnotationParser; -import java.lang.annotation.AnnotationFormatError; -import java.lang.reflect.Modifier; - -/** - * {@code Constructor} provides information about, and access to, a single - * constructor for a class. - * - * <p>{@code Constructor} permits widening conversions to occur when matching the - * actual parameters to newInstance() with the underlying - * constructor's formal parameters, but throws an - * {@code IllegalArgumentException} if a narrowing conversion would occur. - * - * @param <T> the class in which the constructor is declared - * - * @see Member - * @see java.lang.Class - * @see java.lang.Class#getConstructors() - * @see java.lang.Class#getConstructor(Class[]) - * @see java.lang.Class#getDeclaredConstructors() - * - * @author Kenneth Russell - * @author Nakul Saraiya - */ -public final - class Constructor<T> extends AccessibleObject implements - GenericDeclaration, - Member { - - private Class<T> clazz; - private int slot; - private Class<?>[] parameterTypes; - private Class<?>[] exceptionTypes; - private int modifiers; - // Generics and annotations support - private transient String signature; - // generic info repository; lazily initialized - private transient ConstructorRepository genericInfo; - - // Generics infrastructure - // Accessor for factory - private GenericsFactory getFactory() { - // create scope and factory - return CoreReflectionFactory.make(this, ConstructorScope.make(this)); - } - - // Accessor for generic info repository - private ConstructorRepository getGenericInfo() { - // lazily initialize repository if necessary - if (genericInfo == null) { - // create and cache generic info repository - genericInfo = - ConstructorRepository.make(getSignature(), - getFactory()); - } - return genericInfo; //return cached repository - } - - private volatile ConstructorAccessor constructorAccessor; - // For sharing of ConstructorAccessors. This branching structure - // is currently only two levels deep (i.e., one root Constructor - // and potentially many Constructor objects pointing to it.) - private Constructor<T> root; - - /** - * Package-private constructor used by ReflectAccess to enable - * instantiation of these objects in Java code from the java.lang - * package via sun.reflect.LangReflectAccess. - */ - Constructor(Class<T> declaringClass, - Class<?>[] parameterTypes, - Class<?>[] checkedExceptions, - int modifiers, - int slot, - String signature, - byte[] unused1, - byte[] unused2) - { - this.clazz = declaringClass; - this.parameterTypes = parameterTypes; - this.exceptionTypes = checkedExceptions; - this.modifiers = modifiers; - this.slot = slot; - this.signature = signature; - } - - /** - * Package-private routine (exposed to java.lang.Class via - * ReflectAccess) which returns a copy of this Constructor. The copy's - * "root" field points to this Constructor. - */ - Constructor<T> copy() { - // This routine enables sharing of ConstructorAccessor objects - // among Constructor 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.) - Constructor<T> res = new Constructor<>(clazz, - parameterTypes, - exceptionTypes, modifiers, slot, - signature, - null, - null); - res.root = this; - // Might as well eagerly propagate this if already present - res.constructorAccessor = constructorAccessor; - return res; - } - - /** - * Returns the {@code Class} object representing the class that declares - * the constructor represented by this {@code Constructor} object. - */ - public Class<T> getDeclaringClass() { - return clazz; - } - - /** - * Returns the name of this constructor, as a string. This is - * the binary name of the constructor's declaring class. - */ - public String getName() { - return getDeclaringClass().getName(); - } - - /** - * Returns the Java language modifiers for the constructor - * represented by this {@code Constructor} 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 - * <cite>The Java™ Virtual Machine Specification</cite> - * @since 1.5 - */ - public TypeVariable<Constructor<T>>[] getTypeParameters() { - if (getSignature() != null) { - return (TypeVariable<Constructor<T>>[])getGenericInfo().getTypeParameters(); - } else - return (TypeVariable<Constructor<T>>[])new TypeVariable[0]; - } - - - /** - * Returns an array of {@code Class} objects that represent the formal - * parameter types, in declaration order, of the constructor - * represented by this {@code Constructor} object. Returns an array of - * length 0 if the underlying constructor takes no parameters. - * - * @return the parameter types for the constructor 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 Constructor} 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 {@code Type}s 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 - * <cite>The Java™ Virtual Machine Specification</cite> - * @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 (getSignature() != null) - return getGenericInfo().getParameterTypes(); - else - return getParameterTypes(); - } - - - /** - * Returns an array of {@code Class} objects that represent the types - * of exceptions declared to be thrown by the underlying constructor - * represented by this {@code Constructor} object. Returns an array of - * length 0 if the constructor declares no exceptions in its {@code throws} clause. - * - * @return the exception types declared as being thrown by the - * constructor 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 Constructor} 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 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 - * <cite>The Java™ Virtual Machine Specification</cite> - * @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 (getSignature() != null && - ( (result = getGenericInfo().getExceptionTypes()).length > 0 )) - return result; - else - return getExceptionTypes(); - } - - /** - * Compares this {@code Constructor} against the specified object. - * Returns true if the objects are the same. Two {@code Constructor} objects are - * the same if they were declared by the same class and have the - * same formal parameter types. - */ - public boolean equals(Object obj) { - if (obj != null && obj instanceof Constructor) { - Constructor<?> other = (Constructor<?>)obj; - if (getDeclaringClass() == other.getDeclaringClass()) { - /* 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 Constructor}. The hashcode is - * the same as the hashcode for the underlying constructor's - * declaring class name. - */ - public int hashCode() { - return getDeclaringClass().getName().hashCode(); - } - - /** - * Returns a string describing this {@code Constructor}. The string is - * formatted as the constructor access modifiers, if any, - * followed by the fully-qualified name of the declaring class, - * followed by a parenthesized, comma-separated list of the - * constructor's formal parameter types. For example: - * <pre> - * public java.util.Hashtable(int,float) - * </pre> - * - * <p>The only possible modifiers for constructors are the access - * modifiers {@code public}, {@code protected} or - * {@code private}. Only one of these may appear, or none if the - * constructor has default (package) access. - */ - public String toString() { - try { - StringBuffer sb = new StringBuffer(); - int mod = getModifiers() & Modifier.constructorModifiers(); - if (mod != 0) { - sb.append(Modifier.toString(mod) + " "); - } - sb.append(Field.getTypeName(getDeclaringClass())); - sb.append("("); - 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 Constructor}, - * including type parameters. The string is formatted as the - * constructor access modifiers, if any, followed by an - * angle-bracketed comma separated list of the constructor's type - * parameters, if any, followed by the fully-qualified name of the - * declaring class, followed by a parenthesized, comma-separated - * list of the constructor's generic formal parameter types. - * - * If this constructor was declared to take a variable number of - * arguments, instead of denoting the last parameter as - * "<tt><i>Type</i>[]</tt>", it is denoted as - * "<tt><i>Type</i>...</tt>". - * - * 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 constructor is declared to throw - * exceptions, the parameter list is followed by a space, followed - * by the word "{@code throws}" followed by a - * comma-separated list of the thrown exception types. - * - * <p>The only possible modifiers for constructors are the access - * modifiers {@code public}, {@code protected} or - * {@code private}. Only one of these may appear, or none if the - * constructor has default (package) access. - * - * @return a string describing this {@code Constructor}, - * include type parameters - * - * @since 1.5 - */ - public String toGenericString() { - try { - StringBuilder sb = new StringBuilder(); - int mod = getModifiers() & Modifier.constructorModifiers(); - 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("> "); - } - sb.append(Field.getTypeName(getDeclaringClass())); - sb.append("("); - 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()); - if (isVarArgs() && (j == params.length - 1)) // replace T[] with T... - param = param.replaceFirst("\\[\\]$", "..."); - 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 + ">"; - } - } - - /** - * Uses the constructor represented by this {@code Constructor} object to - * create and initialize a new instance of the constructor's - * declaring class, with the specified initialization 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 number of formal parameters required by the underlying constructor - * is 0, the supplied {@code initargs} array may be of length 0 or null. - * - * <p>If the constructor's declaring class is an inner class in a - * non-static context, the first argument to the constructor needs - * to be the enclosing instance; see section 15.9.3 of - * <cite>The Java™ Language Specification</cite>. - * - * <p>If the required access and argument checks succeed and the - * instantiation will proceed, the constructor's declaring class - * is initialized if it has not already been initialized. - * - * <p>If the constructor completes normally, returns the newly - * created and initialized instance. - * - * @param initargs array of objects to be passed as arguments to - * the constructor call; values of primitive types are wrapped in - * a wrapper object of the appropriate type (e.g. a {@code float} - * in a {@link java.lang.Float Float}) - * - * @return a new object created by calling the constructor - * this object represents - * - * @exception IllegalAccessException if this {@code Constructor} object - * is enforcing Java language access control and the underlying - * constructor is inaccessible. - * @exception IllegalArgumentException 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; if - * this constructor pertains to an enum type. - * @exception InstantiationException if the class that declares the - * underlying constructor represents an abstract class. - * @exception InvocationTargetException if the underlying constructor - * throws an exception. - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails. - */ - @CallerSensitive - public T newInstance(Object ... initargs) - throws InstantiationException, IllegalAccessException, - IllegalArgumentException, InvocationTargetException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - Class<?> caller = Reflection.getCallerClass(); - checkAccess(caller, clazz, null, modifiers); - } - } - if ((clazz.getModifiers() & Modifier.ENUM) != 0) - throw new IllegalArgumentException("Cannot reflectively create enum objects"); - ConstructorAccessor ca = constructorAccessor; // read volatile - if (ca == null) { - ca = acquireConstructorAccessor(); - } - return (T) ca.newInstance(initargs); - } - - /** - * Returns {@code true} if this constructor was declared to take - * a variable number of arguments; returns {@code false} - * otherwise. - * - * @return {@code true} if an only if this constructor 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 constructor is a synthetic - * constructor; returns {@code false} otherwise. - * - * @return true if and only if this constructor is a synthetic - * constructor as defined by - * <cite>The Java™ Language Specification</cite>. - * @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 - // ConstructorAccessor for a given Constructor. However, avoiding - // synchronization will probably make the implementation more - // scalable. - private ConstructorAccessor acquireConstructorAccessor() { - // First check to see if one has been created yet, and take it - // if so. - ConstructorAccessor tmp = null; - if (root != null) tmp = root.getConstructorAccessor(); - if (tmp != null) { - constructorAccessor = tmp; - } else { - // Otherwise fabricate one and propagate it up to the root - tmp = reflectionFactory.newConstructorAccessor(this); - setConstructorAccessor(tmp); - } - - return tmp; - } - - // Returns ConstructorAccessor for this Constructor object, not - // looking up the chain to the root - ConstructorAccessor getConstructorAccessor() { - return constructorAccessor; - } - - // Sets the ConstructorAccessor for this Constructor object and - // (recursively) its root - void setConstructorAccessor(ConstructorAccessor accessor) { - constructorAccessor = accessor; - // Propagate up - if (root != null) { - root.setConstructorAccessor(accessor); - } - } - - int getSlot() { - return slot; - } - - String getSignature() { - return signature; - } - - byte[] getRawAnnotations() { - return null; - } - - byte[] getRawParameterAnnotations() { - return null; - } - - /** - * @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); - } - - private static final Annotation[] EMPTY_ANNOTATION_ARRAY=new Annotation[0]; - - /** - * @since 1.5 - */ - public Annotation[] getDeclaredAnnotations() { - return declaredAnnotations().values().toArray(EMPTY_ANNOTATION_ARRAY); - } - - private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations; - - private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() { - if (declaredAnnotations == null) { - declaredAnnotations = Method.getDeclaredAnnotationsImpl(this); - } - return declaredAnnotations; - } - - /** - * Returns an array of arrays that represent the annotations on the formal - * parameters, in declaration order, of the method represented by - * this {@code Constructor} 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 - * Constructor object - * @since 1.5 - */ - public Annotation[][] getParameterAnnotations() { - int numParameters = parameterTypes.length; - Annotation[][] result = Method.getParameterAnnotationsImpl(this); - if (result == null) - return new Annotation[numParameters][0]; - if (result.length != numParameters) { - Class<?> declaringClass = getDeclaringClass(); - if (declaringClass.isEnum() || - declaringClass.isAnonymousClass() || - declaringClass.isLocalClass() ) - ; // Can't do reliable parameter counting - else { - if (!declaringClass.isMemberClass() || // top-level - // Check for the enclosing instance parameter for - // non-static member classes - (declaringClass.isMemberClass() && - ((declaringClass.getModifiers() & Modifier.STATIC) == 0) && - result.length + 1 != numParameters) ) { - throw new AnnotationFormatError( - "Parameter annotations don't match number of parameters"); - } - } - } - return result; - } -} diff --git a/openjdk/java/lang/reflect/Field.java b/openjdk/java/lang/reflect/Field.java deleted file mode 100644 index b2cb46b3..00000000 --- a/openjdk/java/lang/reflect/Field.java +++ /dev/null @@ -1,1134 +0,0 @@ -/* - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang.reflect; - -import sun.reflect.CallerSensitive; -import sun.reflect.FieldAccessor; -import sun.reflect.Reflection; -import sun.reflect.generics.repository.FieldRepository; -import sun.reflect.generics.factory.CoreReflectionFactory; -import sun.reflect.generics.factory.GenericsFactory; -import sun.reflect.generics.scope.ClassScope; -import java.lang.annotation.Annotation; -import java.util.Map; -import sun.reflect.annotation.AnnotationParser; - - -/** - * A {@code Field} provides information about, and dynamic access to, a - * single field of a class or an interface. The reflected field may - * be a class (static) field or an instance field. - * - * <p>A {@code Field} permits widening conversions to occur during a get or - * set access operation, but throws an {@code IllegalArgumentException} if a - * narrowing conversion would occur. - * - * @see Member - * @see java.lang.Class - * @see java.lang.Class#getFields() - * @see java.lang.Class#getField(String) - * @see java.lang.Class#getDeclaredFields() - * @see java.lang.Class#getDeclaredField(String) - * - * @author Kenneth Russell - * @author Nakul Saraiya - */ -public final -class Field extends AccessibleObject implements 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<?> type; - private int modifiers; - // Generics and annotations support - private transient String signature; - // generic info repository; lazily initialized - private transient FieldRepository genericInfo; - // Cached field accessor created without override - private FieldAccessor fieldAccessor; - // Cached field accessor created with override - private FieldAccessor overrideFieldAccessor; - // For sharing of FieldAccessors. This branching structure is - // currently only two levels deep (i.e., one root Field and - // potentially many Field objects pointing to it.) - private Field root; - - // Generics infrastructure - - private String getGenericSignature() {return signature;} - - // Accessor for factory - private GenericsFactory getFactory() { - Class<?> c = getDeclaringClass(); - // create scope and factory - return CoreReflectionFactory.make(c, ClassScope.make(c)); - } - - // Accessor for generic info repository - private FieldRepository getGenericInfo() { - // lazily initialize repository if necessary - if (genericInfo == null) { - // create and cache generic info repository - genericInfo = FieldRepository.make(getGenericSignature(), - getFactory()); - } - return genericInfo; //return cached repository - } - - - /** - * Package-private constructor used by ReflectAccess to enable - * instantiation of these objects in Java code from the java.lang - * package via sun.reflect.LangReflectAccess. - */ - Field(Class<?> declaringClass, - String name, - Class<?> type, - int modifiers, - int slot, - String signature, - byte[] unused) - { - this.clazz = declaringClass; - this.name = name; - this.type = type; - this.modifiers = modifiers; - this.slot = slot; - this.signature = signature; - } - - /** - * Package-private routine (exposed to java.lang.Class via - * ReflectAccess) which returns a copy of this Field. The copy's - * "root" field points to this Field. - */ - Field copy() { - // This routine enables sharing of FieldAccessor objects - // among Field 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.) - Field res = new Field(clazz, name, type, modifiers, slot, signature, null); - res.root = this; - // Might as well eagerly propagate this if already present - res.fieldAccessor = fieldAccessor; - res.overrideFieldAccessor = overrideFieldAccessor; - return res; - } - - /** - * Returns the {@code Class} object representing the class or interface - * that declares the field represented by this {@code Field} object. - */ - public Class<?> getDeclaringClass() { - return clazz; - } - - /** - * Returns the name of the field represented by this {@code Field} object. - */ - public String getName() { - return name; - } - - /** - * Returns the Java language modifiers for the field represented - * by this {@code Field} object, as an integer. The {@code Modifier} class should - * be used to decode the modifiers. - * - * @see Modifier - */ - public int getModifiers() { - return modifiers; - } - - /** - * Returns {@code true} if this field represents an element of - * an enumerated type; returns {@code false} otherwise. - * - * @return {@code true} if and only if this field represents an element of - * an enumerated type. - * @since 1.5 - */ - public boolean isEnumConstant() { - return (getModifiers() & Modifier.ENUM) != 0; - } - - /** - * Returns {@code true} if this field is a synthetic - * field; returns {@code false} otherwise. - * - * @return true if and only if this field is a synthetic - * field as defined by the Java Language Specification. - * @since 1.5 - */ - public boolean isSynthetic() { - return Modifier.isSynthetic(getModifiers()); - } - - /** - * Returns a {@code Class} object that identifies the - * declared type for the field represented by this - * {@code Field} object. - * - * @return a {@code Class} object identifying the declared - * type of the field represented by this object - */ - public Class<?> getType() { - return type; - } - - /** - * Returns a {@code Type} object that represents the declared type for - * the field represented by this {@code Field} object. - * - * <p>If the {@code 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 type of the underlying field is a type variable or a - * parameterized type, it is created. Otherwise, it is resolved. - * - * @return a {@code Type} object that represents the declared type for - * the field represented by this {@code Field} object - * @throws GenericSignatureFormatError if the generic field - * signature does not conform to the format specified in - * <cite>The Java™ Virtual Machine Specification</cite> - * @throws TypeNotPresentException if the generic type - * signature of the underlying field refers to a non-existent - * type declaration - * @throws MalformedParameterizedTypeException if the generic - * signature of the underlying field refers to a parameterized type - * that cannot be instantiated for any reason - * @since 1.5 - */ - public Type getGenericType() { - if (getGenericSignature() != null) - return getGenericInfo().getGenericType(); - else - return getType(); - } - - - /** - * Compares this {@code Field} against the specified object. Returns - * true if the objects are the same. Two {@code Field} objects are the same if - * they were declared by the same class and have the same name - * and type. - */ - public boolean equals(Object obj) { - if (obj != null && obj instanceof Field) { - Field other = (Field)obj; - return (getDeclaringClass() == other.getDeclaringClass()) - && (getName() == other.getName()) - && (getType() == other.getType()); - } - return false; - } - - /** - * Returns a hashcode for this {@code Field}. This is computed as the - * exclusive-or of the hashcodes for the underlying field's - * declaring class name and its name. - */ - public int hashCode() { - return getDeclaringClass().getName().hashCode() ^ getName().hashCode(); - } - - /** - * Returns a string describing this {@code Field}. The format is - * the access modifiers for the field, if any, followed - * by the field type, followed by a space, followed by - * the fully-qualified name of the class declaring the field, - * followed by a period, followed by the name of the field. - * For example: - * <pre> - * public static final int java.lang.Thread.MIN_PRIORITY - * private int java.io.FileDescriptor.fd - * </pre> - * - * <p>The 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 static}, {@code final}, - * {@code transient}, {@code volatile}. - */ - public String toString() { - int mod = getModifiers(); - return (((mod == 0) ? "" : (Modifier.toString(mod) + " ")) - + getTypeName(getType()) + " " - + getTypeName(getDeclaringClass()) + "." - + getName()); - } - - /** - * Returns a string describing this {@code Field}, including - * its generic type. The format is the access modifiers for the - * field, if any, followed by the generic field type, followed by - * a space, followed by the fully-qualified name of the class - * declaring the field, followed by a period, followed by the name - * of the field. - * - * <p>The 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 static}, {@code final}, - * {@code transient}, {@code volatile}. - * - * @return a string describing this {@code Field}, including - * its generic type - * - * @since 1.5 - */ - public String toGenericString() { - int mod = getModifiers(); - Type fieldType = getGenericType(); - return (((mod == 0) ? "" : (Modifier.toString(mod) + " ")) - + ((fieldType instanceof Class) ? - getTypeName((Class)fieldType): fieldType.toString())+ " " - + getTypeName(getDeclaringClass()) + "." - + getName()); - } - - /** - * Returns the value of the field represented by this {@code Field}, on - * the specified object. The value is automatically wrapped in an - * object if it has a primitive type. - * - * <p>The underlying field's value is obtained as follows: - * - * <p>If the underlying field is a static field, the {@code obj} argument - * is ignored; it may be null. - * - * <p>Otherwise, the underlying field is an instance field. If the - * specified {@code obj} argument is null, the method throws a - * {@code NullPointerException}. If the specified object is not an - * instance of the class or interface declaring the underlying - * field, the method throws an {@code IllegalArgumentException}. - * - * <p>If this {@code Field} object is enforcing Java language access control, and - * the underlying field is inaccessible, the method throws an - * {@code IllegalAccessException}. - * If the underlying field is static, the class that declared the - * field is initialized if it has not already been initialized. - * - * <p>Otherwise, the value is retrieved from the underlying instance - * or static field. If the field has a primitive type, the value - * is wrapped in an object before being returned, otherwise it is - * returned as is. - * - * <p>If the field is hidden in the type of {@code obj}, - * the field's value is obtained according to the preceding rules. - * - * @param obj object from which the represented field's value is - * to be extracted - * @return the value of the represented field in object - * {@code obj}; primitive values are wrapped in an appropriate - * object before being returned - * - * @exception IllegalAccessException if this {@code Field} object - * is enforcing Java language access control and the underlying - * field is inaccessible. - * @exception IllegalArgumentException if the specified object is not an - * instance of the class or interface declaring the underlying - * field (or a subclass or implementor thereof). - * @exception NullPointerException if the specified object is null - * and the field is an instance field. - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails. - */ - @CallerSensitive - public Object get(Object obj) - throws IllegalArgumentException, IllegalAccessException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers); - } - } - return getFieldAccessor(obj).get(obj); - } - - /** - * Gets the value of a static or instance {@code boolean} field. - * - * @param obj the object to extract the {@code boolean} value - * from - * @return the value of the {@code boolean} field - * - * @exception IllegalAccessException if this {@code Field} object - * is enforcing Java language access control and the underlying - * field is inaccessible. - * @exception IllegalArgumentException if the specified object is not - * an instance of the class or interface declaring the - * underlying field (or a subclass or implementor - * thereof), or if the field value cannot be - * converted to the type {@code boolean} by a - * widening conversion. - * @exception NullPointerException if the specified object is null - * and the field is an instance field. - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails. - * @see Field#get - */ - @CallerSensitive - public boolean getBoolean(Object obj) - throws IllegalArgumentException, IllegalAccessException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers); - } - } - return getFieldAccessor(obj).getBoolean(obj); - } - - /** - * Gets the value of a static or instance {@code byte} field. - * - * @param obj the object to extract the {@code byte} value - * from - * @return the value of the {@code byte} field - * - * @exception IllegalAccessException if this {@code Field} object - * is enforcing Java language access control and the underlying - * field is inaccessible. - * @exception IllegalArgumentException if the specified object is not - * an instance of the class or interface declaring the - * underlying field (or a subclass or implementor - * thereof), or if the field value cannot be - * converted to the type {@code byte} by a - * widening conversion. - * @exception NullPointerException if the specified object is null - * and the field is an instance field. - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails. - * @see Field#get - */ - @CallerSensitive - public byte getByte(Object obj) - throws IllegalArgumentException, IllegalAccessException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers); - } - } - return getFieldAccessor(obj).getByte(obj); - } - - /** - * Gets the value of a static or instance field of type - * {@code char} or of another primitive type convertible to - * type {@code char} via a widening conversion. - * - * @param obj the object to extract the {@code char} value - * from - * @return the value of the field converted to type {@code char} - * - * @exception IllegalAccessException if this {@code Field} object - * is enforcing Java language access control and the underlying - * field is inaccessible. - * @exception IllegalArgumentException if the specified object is not - * an instance of the class or interface declaring the - * underlying field (or a subclass or implementor - * thereof), or if the field value cannot be - * converted to the type {@code char} by a - * widening conversion. - * @exception NullPointerException if the specified object is null - * and the field is an instance field. - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails. - * @see Field#get - */ - @CallerSensitive - public char getChar(Object obj) - throws IllegalArgumentException, IllegalAccessException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers); - } - } - return getFieldAccessor(obj).getChar(obj); - } - - /** - * Gets the value of a static or instance field of type - * {@code short} or of another primitive type convertible to - * type {@code short} via a widening conversion. - * - * @param obj the object to extract the {@code short} value - * from - * @return the value of the field converted to type {@code short} - * - * @exception IllegalAccessException if this {@code Field} object - * is enforcing Java language access control and the underlying - * field is inaccessible. - * @exception IllegalArgumentException if the specified object is not - * an instance of the class or interface declaring the - * underlying field (or a subclass or implementor - * thereof), or if the field value cannot be - * converted to the type {@code short} by a - * widening conversion. - * @exception NullPointerException if the specified object is null - * and the field is an instance field. - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails. - * @see Field#get - */ - @CallerSensitive - public short getShort(Object obj) - throws IllegalArgumentException, IllegalAccessException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers); - } - } - return getFieldAccessor(obj).getShort(obj); - } - - /** - * Gets the value of a static or instance field of type - * {@code int} or of another primitive type convertible to - * type {@code int} via a widening conversion. - * - * @param obj the object to extract the {@code int} value - * from - * @return the value of the field converted to type {@code int} - * - * @exception IllegalAccessException if this {@code Field} object - * is enforcing Java language access control and the underlying - * field is inaccessible. - * @exception IllegalArgumentException if the specified object is not - * an instance of the class or interface declaring the - * underlying field (or a subclass or implementor - * thereof), or if the field value cannot be - * converted to the type {@code int} by a - * widening conversion. - * @exception NullPointerException if the specified object is null - * and the field is an instance field. - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails. - * @see Field#get - */ - @CallerSensitive - public int getInt(Object obj) - throws IllegalArgumentException, IllegalAccessException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers); - } - } - return getFieldAccessor(obj).getInt(obj); - } - - /** - * Gets the value of a static or instance field of type - * {@code long} or of another primitive type convertible to - * type {@code long} via a widening conversion. - * - * @param obj the object to extract the {@code long} value - * from - * @return the value of the field converted to type {@code long} - * - * @exception IllegalAccessException if this {@code Field} object - * is enforcing Java language access control and the underlying - * field is inaccessible. - * @exception IllegalArgumentException if the specified object is not - * an instance of the class or interface declaring the - * underlying field (or a subclass or implementor - * thereof), or if the field value cannot be - * converted to the type {@code long} by a - * widening conversion. - * @exception NullPointerException if the specified object is null - * and the field is an instance field. - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails. - * @see Field#get - */ - @CallerSensitive - public long getLong(Object obj) - throws IllegalArgumentException, IllegalAccessException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers); - } - } - return getFieldAccessor(obj).getLong(obj); - } - - /** - * Gets the value of a static or instance field of type - * {@code float} or of another primitive type convertible to - * type {@code float} via a widening conversion. - * - * @param obj the object to extract the {@code float} value - * from - * @return the value of the field converted to type {@code float} - * - * @exception IllegalAccessException if this {@code Field} object - * is enforcing Java language access control and the underlying - * field is inaccessible. - * @exception IllegalArgumentException if the specified object is not - * an instance of the class or interface declaring the - * underlying field (or a subclass or implementor - * thereof), or if the field value cannot be - * converted to the type {@code float} by a - * widening conversion. - * @exception NullPointerException if the specified object is null - * and the field is an instance field. - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails. - * @see Field#get - */ - @CallerSensitive - public float getFloat(Object obj) - throws IllegalArgumentException, IllegalAccessException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers); - } - } - return getFieldAccessor(obj).getFloat(obj); - } - - /** - * Gets the value of a static or instance field of type - * {@code double} or of another primitive type convertible to - * type {@code double} via a widening conversion. - * - * @param obj the object to extract the {@code double} value - * from - * @return the value of the field converted to type {@code double} - * - * @exception IllegalAccessException if this {@code Field} object - * is enforcing Java language access control and the underlying - * field is inaccessible. - * @exception IllegalArgumentException if the specified object is not - * an instance of the class or interface declaring the - * underlying field (or a subclass or implementor - * thereof), or if the field value cannot be - * converted to the type {@code double} by a - * widening conversion. - * @exception NullPointerException if the specified object is null - * and the field is an instance field. - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails. - * @see Field#get - */ - @CallerSensitive - public double getDouble(Object obj) - throws IllegalArgumentException, IllegalAccessException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers); - } - } - return getFieldAccessor(obj).getDouble(obj); - } - - /** - * Sets the field represented by this {@code Field} object on the - * specified object argument to the specified new value. The new - * value is automatically unwrapped if the underlying field has a - * primitive type. - * - * <p>The operation proceeds as follows: - * - * <p>If the underlying field is static, the {@code obj} argument is - * ignored; it may be null. - * - * <p>Otherwise the underlying field is an instance field. If the - * specified object argument is null, the method throws a - * {@code NullPointerException}. If the specified object argument is not - * an instance of the class or interface declaring the underlying - * field, the method throws an {@code IllegalArgumentException}. - * - * <p>If this {@code Field} object is enforcing Java language access control, and - * the underlying field is inaccessible, the method throws an - * {@code IllegalAccessException}. - * - * <p>If the underlying field is final, the method throws an - * {@code IllegalAccessException} unless {@code setAccessible(true)} - * has succeeded for this {@code Field} object - * and the field is non-static. Setting a final field in this way - * is meaningful only during deserialization or reconstruction of - * instances of classes with blank final fields, before they are - * made available for access by other parts of a program. Use in - * any other context may have unpredictable effects, including cases - * in which other parts of a program continue to use the original - * value of this field. - * - * <p>If the underlying field is of a primitive type, an unwrapping - * conversion is attempted to convert the new value to a value of - * a primitive type. If this attempt fails, the method throws an - * {@code IllegalArgumentException}. - * - * <p>If, after possible unwrapping, the new value cannot be - * converted to the type of the underlying field by an identity or - * widening conversion, the method throws an - * {@code IllegalArgumentException}. - * - * <p>If the underlying field is static, the class that declared the - * field is initialized if it has not already been initialized. - * - * <p>The field is set to the possibly unwrapped and widened new value. - * - * <p>If the field is hidden in the type of {@code obj}, - * the field's value is set according to the preceding rules. - * - * @param obj the object whose field should be modified - * @param value the new value for the field of {@code obj} - * being modified - * - * @exception IllegalAccessException if this {@code Field} object - * is enforcing Java language access control and the underlying - * field is either inaccessible or final. - * @exception IllegalArgumentException if the specified object is not an - * instance of the class or interface declaring the underlying - * field (or a subclass or implementor thereof), - * or if an unwrapping conversion fails. - * @exception NullPointerException if the specified object is null - * and the field is an instance field. - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails. - */ - @CallerSensitive - public void set(Object obj, Object value) - throws IllegalArgumentException, IllegalAccessException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers); - } - } - getFieldAccessor(obj).set(obj, value); - } - - /** - * Sets the value of a field as a {@code boolean} on the specified object. - * This method is equivalent to - * {@code set(obj, zObj)}, - * where {@code zObj} is a {@code Boolean} object and - * {@code zObj.booleanValue() == z}. - * - * @param obj the object whose field should be modified - * @param z the new value for the field of {@code obj} - * being modified - * - * @exception IllegalAccessException if this {@code Field} object - * is enforcing Java language access control and the underlying - * field is either inaccessible or final. - * @exception IllegalArgumentException if the specified object is not an - * instance of the class or interface declaring the underlying - * field (or a subclass or implementor thereof), - * or if an unwrapping conversion fails. - * @exception NullPointerException if the specified object is null - * and the field is an instance field. - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails. - * @see Field#set - */ - @CallerSensitive - public void setBoolean(Object obj, boolean z) - throws IllegalArgumentException, IllegalAccessException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers); - } - } - getFieldAccessor(obj).setBoolean(obj, z); - } - - /** - * Sets the value of a field as a {@code byte} on the specified object. - * This method is equivalent to - * {@code set(obj, bObj)}, - * where {@code bObj} is a {@code Byte} object and - * {@code bObj.byteValue() == b}. - * - * @param obj the object whose field should be modified - * @param b the new value for the field of {@code obj} - * being modified - * - * @exception IllegalAccessException if this {@code Field} object - * is enforcing Java language access control and the underlying - * field is either inaccessible or final. - * @exception IllegalArgumentException if the specified object is not an - * instance of the class or interface declaring the underlying - * field (or a subclass or implementor thereof), - * or if an unwrapping conversion fails. - * @exception NullPointerException if the specified object is null - * and the field is an instance field. - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails. - * @see Field#set - */ - @CallerSensitive - public void setByte(Object obj, byte b) - throws IllegalArgumentException, IllegalAccessException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers); - } - } - getFieldAccessor(obj).setByte(obj, b); - } - - /** - * Sets the value of a field as a {@code char} on the specified object. - * This method is equivalent to - * {@code set(obj, cObj)}, - * where {@code cObj} is a {@code Character} object and - * {@code cObj.charValue() == c}. - * - * @param obj the object whose field should be modified - * @param c the new value for the field of {@code obj} - * being modified - * - * @exception IllegalAccessException if this {@code Field} object - * is enforcing Java language access control and the underlying - * field is either inaccessible or final. - * @exception IllegalArgumentException if the specified object is not an - * instance of the class or interface declaring the underlying - * field (or a subclass or implementor thereof), - * or if an unwrapping conversion fails. - * @exception NullPointerException if the specified object is null - * and the field is an instance field. - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails. - * @see Field#set - */ - @CallerSensitive - public void setChar(Object obj, char c) - throws IllegalArgumentException, IllegalAccessException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers); - } - } - getFieldAccessor(obj).setChar(obj, c); - } - - /** - * Sets the value of a field as a {@code short} on the specified object. - * This method is equivalent to - * {@code set(obj, sObj)}, - * where {@code sObj} is a {@code Short} object and - * {@code sObj.shortValue() == s}. - * - * @param obj the object whose field should be modified - * @param s the new value for the field of {@code obj} - * being modified - * - * @exception IllegalAccessException if this {@code Field} object - * is enforcing Java language access control and the underlying - * field is either inaccessible or final. - * @exception IllegalArgumentException if the specified object is not an - * instance of the class or interface declaring the underlying - * field (or a subclass or implementor thereof), - * or if an unwrapping conversion fails. - * @exception NullPointerException if the specified object is null - * and the field is an instance field. - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails. - * @see Field#set - */ - @CallerSensitive - public void setShort(Object obj, short s) - throws IllegalArgumentException, IllegalAccessException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers); - } - } - getFieldAccessor(obj).setShort(obj, s); - } - - /** - * Sets the value of a field as an {@code int} on the specified object. - * This method is equivalent to - * {@code set(obj, iObj)}, - * where {@code iObj} is a {@code Integer} object and - * {@code iObj.intValue() == i}. - * - * @param obj the object whose field should be modified - * @param i the new value for the field of {@code obj} - * being modified - * - * @exception IllegalAccessException if this {@code Field} object - * is enforcing Java language access control and the underlying - * field is either inaccessible or final. - * @exception IllegalArgumentException if the specified object is not an - * instance of the class or interface declaring the underlying - * field (or a subclass or implementor thereof), - * or if an unwrapping conversion fails. - * @exception NullPointerException if the specified object is null - * and the field is an instance field. - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails. - * @see Field#set - */ - @CallerSensitive - public void setInt(Object obj, int i) - throws IllegalArgumentException, IllegalAccessException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers); - } - } - getFieldAccessor(obj).setInt(obj, i); - } - - /** - * Sets the value of a field as a {@code long} on the specified object. - * This method is equivalent to - * {@code set(obj, lObj)}, - * where {@code lObj} is a {@code Long} object and - * {@code lObj.longValue() == l}. - * - * @param obj the object whose field should be modified - * @param l the new value for the field of {@code obj} - * being modified - * - * @exception IllegalAccessException if this {@code Field} object - * is enforcing Java language access control and the underlying - * field is either inaccessible or final. - * @exception IllegalArgumentException if the specified object is not an - * instance of the class or interface declaring the underlying - * field (or a subclass or implementor thereof), - * or if an unwrapping conversion fails. - * @exception NullPointerException if the specified object is null - * and the field is an instance field. - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails. - * @see Field#set - */ - @CallerSensitive - public void setLong(Object obj, long l) - throws IllegalArgumentException, IllegalAccessException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers); - } - } - getFieldAccessor(obj).setLong(obj, l); - } - - /** - * Sets the value of a field as a {@code float} on the specified object. - * This method is equivalent to - * {@code set(obj, fObj)}, - * where {@code fObj} is a {@code Float} object and - * {@code fObj.floatValue() == f}. - * - * @param obj the object whose field should be modified - * @param f the new value for the field of {@code obj} - * being modified - * - * @exception IllegalAccessException if this {@code Field} object - * is enforcing Java language access control and the underlying - * field is either inaccessible or final. - * @exception IllegalArgumentException if the specified object is not an - * instance of the class or interface declaring the underlying - * field (or a subclass or implementor thereof), - * or if an unwrapping conversion fails. - * @exception NullPointerException if the specified object is null - * and the field is an instance field. - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails. - * @see Field#set - */ - @CallerSensitive - public void setFloat(Object obj, float f) - throws IllegalArgumentException, IllegalAccessException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers); - } - } - getFieldAccessor(obj).setFloat(obj, f); - } - - /** - * Sets the value of a field as a {@code double} on the specified object. - * This method is equivalent to - * {@code set(obj, dObj)}, - * where {@code dObj} is a {@code Double} object and - * {@code dObj.doubleValue() == d}. - * - * @param obj the object whose field should be modified - * @param d the new value for the field of {@code obj} - * being modified - * - * @exception IllegalAccessException if this {@code Field} object - * is enforcing Java language access control and the underlying - * field is either inaccessible or final. - * @exception IllegalArgumentException if the specified object is not an - * instance of the class or interface declaring the underlying - * field (or a subclass or implementor thereof), - * or if an unwrapping conversion fails. - * @exception NullPointerException if the specified object is null - * and the field is an instance field. - * @exception ExceptionInInitializerError if the initialization provoked - * by this method fails. - * @see Field#set - */ - @CallerSensitive - public void setDouble(Object obj, double d) - throws IllegalArgumentException, IllegalAccessException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers); - } - } - getFieldAccessor(obj).setDouble(obj, d); - } - - // security check is done before calling this method - private FieldAccessor getFieldAccessor(Object obj) - throws IllegalAccessException - { - boolean ov = override; - FieldAccessor a = (ov) ? overrideFieldAccessor : fieldAccessor; - return (a != null) ? a : acquireFieldAccessor(ov); - } - - // NOTE that there is no synchronization used here. It is correct - // (though not efficient) to generate more than one FieldAccessor - // for a given Field. However, avoiding synchronization will - // probably make the implementation more scalable. - private FieldAccessor acquireFieldAccessor(boolean overrideFinalCheck) { - // First check to see if one has been created yet, and take it - // if so - FieldAccessor tmp = null; - if (root != null) tmp = root.getFieldAccessor(overrideFinalCheck); - if (tmp != null) { - if (overrideFinalCheck) - overrideFieldAccessor = tmp; - else - fieldAccessor = tmp; - } else { - // Otherwise fabricate one and propagate it up to the root - tmp = reflectionFactory.newFieldAccessor(this, overrideFinalCheck); - setFieldAccessor(tmp, overrideFinalCheck); - } - - return tmp; - } - - // Returns FieldAccessor for this Field object, not looking up - // the chain to the root - private FieldAccessor getFieldAccessor(boolean overrideFinalCheck) { - return (overrideFinalCheck)? overrideFieldAccessor : fieldAccessor; - } - - // Sets the FieldAccessor for this Field object and - // (recursively) its root - private void setFieldAccessor(FieldAccessor accessor, boolean overrideFinalCheck) { - if (overrideFinalCheck) - overrideFieldAccessor = accessor; - else - fieldAccessor = accessor; - // Propagate up - if (root != null) { - root.setFieldAccessor(accessor, overrideFinalCheck); - } - } - - /* - * Utility routine to paper over array type names - */ - static String getTypeName(Class<?> type) { - if (type.isArray()) { - try { - Class<?> cl = type; - int dimensions = 0; - while (cl.isArray()) { - dimensions++; - cl = cl.getComponentType(); - } - StringBuffer sb = new StringBuffer(); - sb.append(cl.getName()); - for (int i = 0; i < dimensions; i++) { - sb.append("[]"); - } - return sb.toString(); - } catch (Throwable e) { /*FALLTHRU*/ } - } - return type.getName(); - } - - /** - * @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); - } - - private static final Annotation[] EMPTY_ANNOTATION_ARRAY=new Annotation[0]; - - /** - * @since 1.5 - */ - public Annotation[] getDeclaredAnnotations() { - return declaredAnnotations().values().toArray(EMPTY_ANNOTATION_ARRAY); - } - - private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations; - - private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() { - if (declaredAnnotations == null) { - declaredAnnotations = getDeclaredAnnotationsImpl(); - } - return declaredAnnotations; - } - - private native Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationsImpl(); -} diff --git a/openjdk/java/lang/reflect/Method.java b/openjdk/java/lang/reflect/Method.java deleted file mode 100644 index dce789a4..00000000 --- a/openjdk/java/lang/reflect/Method.java +++ /dev/null @@ -1,749 +0,0 @@ -/* - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang.reflect; - -import ikvm.internal.CallerID; -import sun.reflect.CallerSensitive; -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 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; - - // 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 - } - - /** - * Package-private constructor used by ReflectAccess to enable - * instantiation of these objects in Java code from the java.lang - * package via sun.reflect.LangReflectAccess. - */ - Method(Class<?> declaringClass, - String name, - Class<?>[] parameterTypes, - Class<?> returnType, - Class<?>[] checkedExceptions, - int modifiers, - int slot, - String signature, - byte[] unused1, - byte[] unused2, - byte[] unused3) - { - this.clazz = declaringClass; - this.name = name; - this.parameterTypes = parameterTypes; - this.returnType = returnType; - this.exceptionTypes = checkedExceptions; - this.modifiers = modifiers; - this.slot = slot; - this.signature = signature; - } - - /** - * 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, - null, null, null); - 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 - * <cite>The Java™ Virtual Machine Specification</cite> - * @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 - * <cite>The Java™ Virtual Machine Specification</cite> - * @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 - * <cite>The Java™ Virtual Machine Specification</cite> - * @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 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 - * <cite>The Java™ Virtual Machine Specification</cite> - * @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}, {@code strictfp}. - */ - public String toString() { - try { - StringBuilder sb = new StringBuilder(); - int mod = getModifiers() & Modifier.methodModifiers(); - if (mod != 0) { - sb.append(Modifier.toString(mod)).append(' '); - } - sb.append(Field.getTypeName(getReturnType())).append(' '); - sb.append(Field.getTypeName(getDeclaringClass())).append('.'); - sb.append(getName()).append('('); - 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. - * - * If this method was declared to take a variable number of - * arguments, instead of denoting the last parameter as - * "<tt><i>Type</i>[]</tt>", it is denoted as - * "<tt><i>Type</i>...</tt>". - * - * 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}, {@code strictfp}. - * - * @return a string describing this {@code Method}, - * include type parameters - * - * @since 1.5 - */ - public String toGenericString() { - try { - StringBuilder sb = new StringBuilder(); - int mod = getModifiers() & Modifier.methodModifiers(); - if (mod != 0) { - sb.append(Modifier.toString(mod)).append(' '); - } - 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())) - .append(' '); - - sb.append(Field.getTypeName(getDeclaringClass())).append('.'); - sb.append(getName()).append('('); - 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()); - if (isVarArgs() && (j == params.length - 1)) // replace T[] with T... - param = param.replaceFirst("\\[\\]$", "..."); - 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 - * is enforcing 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. - */ - @CallerSensitive - public Object invoke(Object obj, Object... args) - throws IllegalAccessException, IllegalArgumentException, - InvocationTargetException - { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - Class<?> caller = Reflection.getCallerClass(); - checkAccess(caller, clazz, obj, modifiers); - } - } - MethodAccessor ma = methodAccessor; // read volatile - if (ma == null) { - ma = acquireMethodAccessor(); - } - return ma.invoke(obj, args, CallerID.getCallerID()); - } - - /** - * 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 MethodAccessor 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; - } else { - // Otherwise fabricate one and propagate it up to the root - tmp = reflectionFactory.newMethodAccessor(this); - setMethodAccessor(tmp); - } - - return tmp; - } - - // Returns MethodAccessor for this Method object, not looking up - // the chain to the root - MethodAccessor getMethodAccessor() { - return methodAccessor; - } - - // Sets the MethodAccessor for this Method object and - // (recursively) its root - void setMethodAccessor(MethodAccessor accessor) { - methodAccessor = accessor; - // Propagate up - if (root != null) { - root.setMethodAccessor(accessor); - } - } - - /** - * @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); - } - - private static final Annotation[] EMPTY_ANNOTATION_ARRAY=new Annotation[0]; - - /** - * @since 1.5 - */ - public Annotation[] getDeclaredAnnotations() { - return declaredAnnotations().values().toArray(EMPTY_ANNOTATION_ARRAY); - } - - private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations; - - private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() { - if (declaredAnnotations == null) { - declaredAnnotations = getDeclaredAnnotationsImpl(this); - } - return declaredAnnotations; - } - - static native Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationsImpl(Object methodOrConstructor); - - /** - * Returns the default value for the annotation member represented by - * this {@code Method} instance. If the member is of a primitive type, - * an instance of the corresponding wrapper type is returned. Returns - * null if no default is associated with the member, or if the method - * instance does not represent a declared member of an annotation type. - * - * @return the default value for the annotation member represented - * by this {@code Method} instance. - * @throws TypeNotPresentException if the annotation is of type - * {@link Class} and no definition can be found for the - * default class value. - * @since 1.5 - */ - public native Object getDefaultValue(); - - /** - * Returns an array of arrays that represent the annotations on the formal - * parameters, in declaration order, of the method represented by - * this {@code Method} 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() { - Annotation[][] result = getParameterAnnotationsImpl(this); - int numParameters = parameterTypes.length; - if (result == null) - return new Annotation[numParameters][0]; - - if (result.length != numParameters) - throw new java.lang.annotation.AnnotationFormatError( - "Parameter annotations don't match number of parameters"); - return result; - } - - static native Annotation[][] getParameterAnnotationsImpl(Object methodOrConstructor); -} diff --git a/openjdk/java/lang/reflect/Proxy.java b/openjdk/java/lang/reflect/Proxy.java deleted file mode 100644 index 3d9850e0..00000000 --- a/openjdk/java/lang/reflect/Proxy.java +++ /dev/null @@ -1,815 +0,0 @@ -/* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang.reflect; - -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; -import java.security.AccessController; -import java.security.Permission; -import java.security.PrivilegedAction; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.List; -import java.util.WeakHashMap; -import sun.misc.ProxyGenerator; -import sun.reflect.CallerSensitive; -import sun.reflect.Reflection; -import sun.reflect.misc.ReflectUtil; -import sun.security.util.SecurityConstants; - -/** - * {@code Proxy} provides static methods for creating dynamic proxy - * classes and instances, and it is also the superclass of all - * dynamic proxy classes created by those methods. - * - * <p>To create a proxy for some interface {@code Foo}: - * <pre> - * InvocationHandler handler = new MyInvocationHandler(...); - * Class proxyClass = Proxy.getProxyClass( - * Foo.class.getClassLoader(), new Class[] { Foo.class }); - * Foo f = (Foo) proxyClass. - * getConstructor(new Class[] { InvocationHandler.class }). - * newInstance(new Object[] { handler }); - * </pre> - * or more simply: - * <pre> - * Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), - * new Class[] { Foo.class }, - * handler); - * </pre> - * - * <p>A <i>dynamic proxy class</i> (simply referred to as a <i>proxy - * class</i> below) is a class that implements a list of interfaces - * specified at runtime when the class is created, with behavior as - * described below. - * - * A <i>proxy interface</i> is such an interface that is implemented - * by a proxy class. - * - * A <i>proxy instance</i> is an instance of a proxy class. - * - * Each proxy instance has an associated <i>invocation handler</i> - * object, which implements the interface {@link InvocationHandler}. - * A method invocation on a proxy instance through one of its proxy - * interfaces will be dispatched to the {@link InvocationHandler#invoke - * invoke} method of the instance's invocation handler, passing the proxy - * instance, a {@code java.lang.reflect.Method} object identifying - * the method that was invoked, and an array of type {@code Object} - * containing the arguments. The invocation handler processes the - * encoded method invocation as appropriate and the result that it - * returns will be returned as the result of the method invocation on - * the proxy instance. - * - * <p>A proxy class has the following properties: - * - * <ul> - * <li>Proxy classes are public, final, and not abstract. - * - * <li>The unqualified name of a proxy class is unspecified. The space - * of class names that begin with the string {@code "$Proxy"} - * should be, however, reserved for proxy classes. - * - * <li>A proxy class extends {@code java.lang.reflect.Proxy}. - * - * <li>A proxy class implements exactly the interfaces specified at its - * creation, in the same order. - * - * <li>If a proxy class implements a non-public interface, then it will - * be defined in the same package as that interface. Otherwise, the - * package of a proxy class is also unspecified. Note that package - * sealing will not prevent a proxy class from being successfully defined - * in a particular package at runtime, and neither will classes already - * defined by the same class loader and the same package with particular - * signers. - * - * <li>Since a proxy class implements all of the interfaces specified at - * its creation, invoking {@code getInterfaces} on its - * {@code Class} object will return an array containing the same - * list of interfaces (in the order specified at its creation), invoking - * {@code getMethods} on its {@code Class} object will return - * an array of {@code Method} objects that include all of the - * methods in those interfaces, and invoking {@code getMethod} will - * find methods in the proxy interfaces as would be expected. - * - * <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method will - * return true if it is passed a proxy class-- a class returned by - * {@code Proxy.getProxyClass} or the class of an object returned by - * {@code Proxy.newProxyInstance}-- and false otherwise. - * - * <li>The {@code java.security.ProtectionDomain} of a proxy class - * is the same as that of system classes loaded by the bootstrap class - * loader, such as {@code java.lang.Object}, because the code for a - * proxy class is generated by trusted system code. This protection - * domain will typically be granted - * {@code java.security.AllPermission}. - * - * <li>Each proxy class has one public constructor that takes one argument, - * an implementation of the interface {@link InvocationHandler}, to set - * the invocation handler for a proxy instance. Rather than having to use - * the reflection API to access the public constructor, a proxy instance - * can be also be created by calling the {@link Proxy#newProxyInstance - * Proxy.newProxyInstance} method, which combines the actions of calling - * {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the - * constructor with an invocation handler. - * </ul> - * - * <p>A proxy instance has the following properties: - * - * <ul> - * <li>Given a proxy instance {@code proxy} and one of the - * interfaces implemented by its proxy class {@code Foo}, the - * following expression will return true: - * <pre> - * {@code proxy instanceof Foo} - * </pre> - * and the following cast operation will succeed (rather than throwing - * a {@code ClassCastException}): - * <pre> - * {@code (Foo) proxy} - * </pre> - * - * <li>Each proxy instance has an associated invocation handler, the one - * that was passed to its constructor. The static - * {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method - * will return the invocation handler associated with the proxy instance - * passed as its argument. - * - * <li>An interface method invocation on a proxy instance will be - * encoded and dispatched to the invocation handler's {@link - * InvocationHandler#invoke invoke} method as described in the - * documentation for that method. - * - * <li>An invocation of the {@code hashCode}, - * {@code equals}, or {@code toString} methods declared in - * {@code java.lang.Object} on a proxy instance will be encoded and - * dispatched to the invocation handler's {@code invoke} method in - * the same manner as interface method invocations are encoded and - * dispatched, as described above. The declaring class of the - * {@code Method} object passed to {@code invoke} will be - * {@code java.lang.Object}. Other public methods of a proxy - * instance inherited from {@code java.lang.Object} are not - * overridden by a proxy class, so invocations of those methods behave - * like they do for instances of {@code java.lang.Object}. - * </ul> - * - * <h3>Methods Duplicated in Multiple Proxy Interfaces</h3> - * - * <p>When two or more interfaces of a proxy class contain a method with - * the same name and parameter signature, the order of the proxy class's - * interfaces becomes significant. When such a <i>duplicate method</i> - * is invoked on a proxy instance, the {@code Method} object passed - * to the invocation handler will not necessarily be the one whose - * declaring class is assignable from the reference type of the interface - * that the proxy's method was invoked through. This limitation exists - * because the corresponding method implementation in the generated proxy - * class cannot determine which interface it was invoked through. - * Therefore, when a duplicate method is invoked on a proxy instance, - * the {@code Method} object for the method in the foremost interface - * that contains the method (either directly or inherited through a - * superinterface) in the proxy class's list of interfaces is passed to - * the invocation handler's {@code invoke} method, regardless of the - * reference type through which the method invocation occurred. - * - * <p>If a proxy interface contains a method with the same name and - * parameter signature as the {@code hashCode}, {@code equals}, - * or {@code toString} methods of {@code java.lang.Object}, - * when such a method is invoked on a proxy instance, the - * {@code Method} object passed to the invocation handler will have - * {@code java.lang.Object} as its declaring class. In other words, - * the public, non-final methods of {@code java.lang.Object} - * logically precede all of the proxy interfaces for the determination of - * which {@code Method} object to pass to the invocation handler. - * - * <p>Note also that when a duplicate method is dispatched to an - * invocation handler, the {@code invoke} method may only throw - * checked exception types that are assignable to one of the exception - * types in the {@code throws} clause of the method in <i>all</i> of - * the proxy interfaces that it can be invoked through. If the - * {@code invoke} method throws a checked exception that is not - * assignable to any of the exception types declared by the method in one - * of the proxy interfaces that it can be invoked through, then an - * unchecked {@code UndeclaredThrowableException} will be thrown by - * the invocation on the proxy instance. This restriction means that not - * all of the exception types returned by invoking - * {@code getExceptionTypes} on the {@code Method} object - * passed to the {@code invoke} method can necessarily be thrown - * successfully by the {@code invoke} method. - * - * @author Peter Jones - * @see InvocationHandler - * @since 1.3 - */ -public class Proxy implements java.io.Serializable { - - private static final long serialVersionUID = -2222568056686623797L; - - /** prefix for all proxy class names */ - private final static String proxyClassNamePrefix = "$Proxy"; - - /** parameter types of a proxy class constructor */ - private final static Class[] constructorParams = - { InvocationHandler.class }; - - /** maps a class loader to the proxy class cache for that loader */ - private static Map<ClassLoader, Map<List<String>, Object>> loaderToCache - = new WeakHashMap<>(); - - /** marks that a particular proxy class is currently being generated */ - private static Object pendingGenerationMarker = new Object(); - - /** next number to use for generation of unique proxy class names */ - private static long nextUniqueNumber = 0; - private static Object nextUniqueNumberLock = new Object(); - - /** set of all generated proxy classes, for isProxyClass implementation */ - private static Map<Class<?>, Void> proxyClasses = - Collections.synchronizedMap(new WeakHashMap<Class<?>, Void>()); - - /** - * the invocation handler for this proxy instance. - * @serial - */ - protected InvocationHandler h; - - /** - * Prohibits instantiation. - */ - private Proxy() { - } - - /** - * Constructs a new {@code Proxy} instance from a subclass - * (typically, a dynamic proxy class) with the specified value - * for its invocation handler. - * - * @param h the invocation handler for this proxy instance - */ - protected Proxy(InvocationHandler h) { - doNewInstanceCheck(); - this.h = h; - } - - private static class ProxyAccessHelper { - // The permission is implementation specific. - static final Permission PROXY_PERMISSION = - new ReflectPermission("proxyConstructorNewInstance"); - // These system properties are defined to provide a short-term - // workaround if customers need to disable the new security checks. - static final boolean allowNewInstance; - static final boolean allowNullLoader; - static { - allowNewInstance = getBooleanProperty("sun.reflect.proxy.allowsNewInstance"); - allowNullLoader = getBooleanProperty("sun.reflect.proxy.allowsNullLoader"); - } - - private static boolean getBooleanProperty(final String key) { - String s = AccessController.doPrivileged(new PrivilegedAction<String>() { - public String run() { - return System.getProperty(key); - } - }); - return Boolean.valueOf(s); - } - - static boolean needsNewInstanceCheck(Class<?> proxyClass) { - if (!Proxy.isProxyClass(proxyClass) || allowNewInstance) { - return false; - } - - if (ReflectUtil.isNonPublicProxyClass(proxyClass)) { - for (Class<?> intf : proxyClass.getInterfaces()) { - if (!Modifier.isPublic(intf.getModifiers())) { - return true; - } - } - } - return false; - } - } - - /* - * Access check on a proxy class that implements any non-public interface. - * - * @throws SecurityException if a security manager exists, and - * the caller does not have the permission. - */ - private void doNewInstanceCheck() { - SecurityManager sm = System.getSecurityManager(); - Class<?> proxyClass = this.getClass(); - if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(proxyClass)) { - try { - sm.checkPermission(ProxyAccessHelper.PROXY_PERMISSION); - } catch (SecurityException e) { - throw new SecurityException("Not allowed to construct a Proxy " - + "instance that implements a non-public interface", e); - } - } - } - - /** - * Returns the {@code java.lang.Class} object for a proxy class - * given a class loader and an array of interfaces. The proxy class - * will be defined by the specified class loader and will implement - * all of the supplied interfaces. If a proxy class for the same - * permutation of interfaces has already been defined by the class - * loader, then the existing proxy class will be returned; otherwise, - * a proxy class for those interfaces will be generated dynamically - * and defined by the class loader. - * - * <p>There are several restrictions on the parameters that may be - * passed to {@code Proxy.getProxyClass}: - * - * <ul> - * <li>All of the {@code Class} objects in the - * {@code interfaces} array must represent interfaces, not - * classes or primitive types. - * - * <li>No two elements in the {@code interfaces} array may - * refer to identical {@code Class} objects. - * - * <li>All of the interface types must be visible by name through the - * specified class loader. In other words, for class loader - * {@code cl} and every interface {@code i}, the following - * expression must be true: - * <pre> - * Class.forName(i.getName(), false, cl) == i - * </pre> - * - * <li>All non-public interfaces must be in the same package; - * otherwise, it would not be possible for the proxy class to - * implement all of the interfaces, regardless of what package it is - * defined in. - * - * <li>For any set of member methods of the specified interfaces - * that have the same signature: - * <ul> - * <li>If the return type of any of the methods is a primitive - * type or void, then all of the methods must have that same - * return type. - * <li>Otherwise, one of the methods must have a return type that - * is assignable to all of the return types of the rest of the - * methods. - * </ul> - * - * <li>The resulting proxy class must not exceed any limits imposed - * on classes by the virtual machine. For example, the VM may limit - * the number of interfaces that a class may implement to 65535; in - * that case, the size of the {@code interfaces} array must not - * exceed 65535. - * </ul> - * - * <p>If any of these restrictions are violated, - * {@code Proxy.getProxyClass} will throw an - * {@code IllegalArgumentException}. If the {@code interfaces} - * array argument or any of its elements are {@code null}, a - * {@code NullPointerException} will be thrown. - * - * <p>Note that the order of the specified proxy interfaces is - * significant: two requests for a proxy class with the same combination - * of interfaces but in a different order will result in two distinct - * proxy classes. - * - * @param loader the class loader to define the proxy class - * @param interfaces the list of interfaces for the proxy class - * to implement - * @return a proxy class that is defined in the specified class loader - * and that implements the specified interfaces - * @throws IllegalArgumentException if any of the restrictions on the - * parameters that may be passed to {@code getProxyClass} - * are violated - * @throws NullPointerException if the {@code interfaces} array - * argument or any of its elements are {@code null} - */ - @CallerSensitive - public static Class<?> getProxyClass(ClassLoader loader, - Class<?>... interfaces) - throws IllegalArgumentException - { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkProxyAccess(Reflection.getCallerClass(), loader, interfaces); - } - - return getProxyClass0(loader, interfaces); - } - - /* - * Check permissions required to create a Proxy class. - * - * To define a proxy class, it performs the access checks as in - * Class.forName (VM will invoke ClassLoader.checkPackageAccess): - * 1. "getClassLoader" permission check if loader == null - * 2. checkPackageAccess on the interfaces it implements - * - * To get a constructor and new instance of a proxy class, it performs - * the package access check on the interfaces it implements - * as in Class.getConstructor. - * - * If an interface is non-public, the proxy class must be defined by - * the defining loader of the interface. If the caller's class loader - * is not the same as the defining loader of the interface, the VM - * will throw IllegalAccessError when the generated proxy class is - * being defined via the defineClass0 method. - */ - private static void checkProxyAccess(Class<?> caller, - ClassLoader loader, - Class<?>... interfaces) - { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - ClassLoader ccl = caller.getClassLoader(); - if (loader == null && ccl != null) { - if (!ProxyAccessHelper.allowNullLoader) { - sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); - } - } - ReflectUtil.checkProxyPackageAccess(ccl, interfaces); - } - } - - /** - * Generate a proxy class. Must call the checkProxyAccess method - * to perform permission checks before calling this. - */ - private static Class<?> getProxyClass0(ClassLoader loader, - Class<?>... interfaces) { - if (interfaces.length > 65535) { - throw new IllegalArgumentException("interface limit exceeded"); - } - - Class<?> proxyClass = null; - - /* collect interface names to use as key for proxy class cache */ - String[] interfaceNames = new String[interfaces.length]; - - // for detecting duplicates - Set<Class<?>> interfaceSet = new HashSet<>(); - - for (int i = 0; i < interfaces.length; i++) { - /* - * Verify that the class loader resolves the name of this - * interface to the same Class object. - */ - String interfaceName = interfaces[i].getName(); - Class<?> interfaceClass = null; - try { - interfaceClass = Class.forName(interfaceName, false, loader); - } catch (ClassNotFoundException e) { - } - if (interfaceClass != interfaces[i]) { - throw new IllegalArgumentException( - interfaces[i] + " is not visible from class loader"); - } - - /* - * Verify that the Class object actually represents an - * interface. - */ - if (!interfaceClass.isInterface()) { - throw new IllegalArgumentException( - interfaceClass.getName() + " is not an interface"); - } - - /* - * Verify that this interface is not a duplicate. - */ - if (interfaceSet.contains(interfaceClass)) { - throw new IllegalArgumentException( - "repeated interface: " + interfaceClass.getName()); - } - interfaceSet.add(interfaceClass); - - interfaceNames[i] = interfaceName; - } - - /* - * Using string representations of the proxy interfaces as - * keys in the proxy class cache (instead of their Class - * objects) is sufficient because we require the proxy - * interfaces to be resolvable by name through the supplied - * class loader, and it has the advantage that using a string - * representation of a class makes for an implicit weak - * reference to the class. - */ - List<String> key = Arrays.asList(interfaceNames); - - /* - * Find or create the proxy class cache for the class loader. - */ - Map<List<String>, Object> cache; - synchronized (loaderToCache) { - cache = loaderToCache.get(loader); - if (cache == null) { - cache = new HashMap<>(); - loaderToCache.put(loader, cache); - } - /* - * This mapping will remain valid for the duration of this - * method, without further synchronization, because the mapping - * will only be removed if the class loader becomes unreachable. - */ - } - - /* - * Look up the list of interfaces in the proxy class cache using - * the key. This lookup will result in one of three possible - * kinds of values: - * null, if there is currently no proxy class for the list of - * interfaces in the class loader, - * the pendingGenerationMarker object, if a proxy class for the - * list of interfaces is currently being generated, - * or a weak reference to a Class object, if a proxy class for - * the list of interfaces has already been generated. - */ - synchronized (cache) { - /* - * Note that we need not worry about reaping the cache for - * entries with cleared weak references because if a proxy class - * has been garbage collected, its class loader will have been - * garbage collected as well, so the entire cache will be reaped - * from the loaderToCache map. - */ - do { - Object value = cache.get(key); - if (value instanceof Reference) { - proxyClass = (Class<?>) ((Reference) value).get(); - } - if (proxyClass != null) { - // proxy class already generated: return it - return proxyClass; - } else if (value == pendingGenerationMarker) { - // proxy class being generated: wait for it - try { - cache.wait(); - } catch (InterruptedException e) { - /* - * The class generation that we are waiting for should - * take a small, bounded time, so we can safely ignore - * thread interrupts here. - */ - } - continue; - } else { - /* - * No proxy class for this list of interfaces has been - * generated or is being generated, so we will go and - * generate it now. Mark it as pending generation. - */ - cache.put(key, pendingGenerationMarker); - break; - } - } while (true); - } - - try { - String proxyPkg = null; // package to define proxy class in - - /* - * Record the package of a non-public proxy interface so that the - * proxy class will be defined in the same package. Verify that - * all non-public proxy interfaces are in the same package. - */ - for (int i = 0; i < interfaces.length; i++) { - int flags = interfaces[i].getModifiers(); - if (!Modifier.isPublic(flags)) { - String name = interfaces[i].getName(); - int n = name.lastIndexOf('.'); - String pkg = ((n == -1) ? "" : name.substring(0, n + 1)); - if (proxyPkg == null) { - proxyPkg = pkg; - } else if (!pkg.equals(proxyPkg)) { - throw new IllegalArgumentException( - "non-public interfaces from different packages"); - } - } - } - - if (proxyPkg == null) { - // if no non-public proxy interfaces, use com.sun.proxy package - proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; - } - -generate: do - { - /* - * Choose a name for the proxy class to generate. - */ - long num; - synchronized (nextUniqueNumberLock) { - num = nextUniqueNumber++; - } - String proxyName = proxyPkg + proxyClassNamePrefix + num; - /* - * Verify that the class loader hasn't already - * defined a class with the chosen name. - */ - - proxyClass = getPrecompiledProxy(loader, proxyName, interfaces); - if (proxyClass != null) - break generate; - - /* - * Generate the specified proxy class. - */ - byte[] proxyClassFile = ProxyGenerator.generateProxyClass( - proxyName, interfaces); - try { - proxyClass = defineClass0(loader, proxyName, - proxyClassFile, 0, proxyClassFile.length); - } catch (ClassFormatError e) { - /* - * A ClassFormatError here means that (barring bugs in the - * proxy class generation code) there was some other - * invalid aspect of the arguments supplied to the proxy - * class creation (such as virtual machine limitations - * exceeded). - */ - throw new IllegalArgumentException(e.toString()); - } - } - while (false); - // add to set of all generated proxy classes, for isProxyClass - proxyClasses.put(proxyClass, null); - - } finally { - /* - * We must clean up the "pending generation" state of the proxy - * class cache entry somehow. If a proxy class was successfully - * generated, store it in the cache (with a weak reference); - * otherwise, remove the reserved entry. In all cases, notify - * all waiters on reserved entries in this cache. - */ - synchronized (cache) { - if (proxyClass != null) { - cache.put(key, new WeakReference<Class<?>>(proxyClass)); - } else { - cache.remove(key); - } - cache.notifyAll(); - } - } - return proxyClass; - } - - /** - * Returns an instance of a proxy class for the specified interfaces - * that dispatches method invocations to the specified invocation - * handler. This method is equivalent to: - * <pre> - * Proxy.getProxyClass(loader, interfaces). - * getConstructor(new Class[] { InvocationHandler.class }). - * newInstance(new Object[] { handler }); - * </pre> - * - * <p>{@code Proxy.newProxyInstance} throws - * {@code IllegalArgumentException} for the same reasons that - * {@code Proxy.getProxyClass} does. - * - * @param loader the class loader to define the proxy class - * @param interfaces the list of interfaces for the proxy class - * to implement - * @param h the invocation handler to dispatch method invocations to - * @return a proxy instance with the specified invocation handler of a - * proxy class that is defined by the specified class loader - * and that implements the specified interfaces - * @throws IllegalArgumentException if any of the restrictions on the - * parameters that may be passed to {@code getProxyClass} - * are violated - * @throws NullPointerException if the {@code interfaces} array - * argument or any of its elements are {@code null}, or - * if the invocation handler, {@code h}, is - * {@code null} - */ - @CallerSensitive - public static Object newProxyInstance(ClassLoader loader, - Class<?>[] interfaces, - InvocationHandler h) - throws IllegalArgumentException - { - if (h == null) { - throw new NullPointerException(); - } - - final SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkProxyAccess(Reflection.getCallerClass(), loader, interfaces); - } - - /* - * Look up or generate the designated proxy class. - */ - Class<?> cl = getProxyClass0(loader, interfaces); - - /* - * Invoke its constructor with the designated invocation handler. - */ - try { - final Constructor<?> cons = cl.getConstructor(constructorParams); - final InvocationHandler ih = h; - if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) { - // create proxy instance with doPrivilege as the proxy class may - // implement non-public interfaces that requires a special permission - return AccessController.doPrivileged(new PrivilegedAction<Object>() { - public Object run() { - return newInstance(cons, ih); - } - }); - } else { - return newInstance(cons, ih); - } - } catch (NoSuchMethodException e) { - throw new InternalError(e.toString()); - } - } - - private static Object newInstance(Constructor<?> cons, InvocationHandler h) { - try { - return cons.newInstance(new Object[] {h} ); - } catch (IllegalAccessException | InstantiationException e) { - throw new InternalError(e.toString()); - } catch (InvocationTargetException e) { - Throwable t = e.getCause(); - if (t instanceof RuntimeException) { - throw (RuntimeException) t; - } else { - throw new InternalError(t.toString()); - } - } - } - - /** - * Returns true if and only if the specified class was dynamically - * generated to be a proxy class using the {@code getProxyClass} - * method or the {@code newProxyInstance} method. - * - * <p>The reliability of this method is important for the ability - * to use it to make security decisions, so its implementation should - * not just test if the class in question extends {@code Proxy}. - * - * @param cl the class to test - * @return {@code true} if the class is a proxy class and - * {@code false} otherwise - * @throws NullPointerException if {@code cl} is {@code null} - */ - public static boolean isProxyClass(Class<?> cl) { - if (cl == null) { - throw new NullPointerException(); - } - - return proxyClasses.containsKey(cl); - } - - /** - * Returns the invocation handler for the specified proxy instance. - * - * @param proxy the proxy instance to return the invocation handler for - * @return the invocation handler for the proxy instance - * @throws IllegalArgumentException if the argument is not a - * proxy instance - */ - public static InvocationHandler getInvocationHandler(Object proxy) - throws IllegalArgumentException - { - /* - * Verify that the object is actually a proxy instance. - */ - if (!isProxyClass(proxy.getClass())) { - throw new IllegalArgumentException("not a proxy instance"); - } - - Proxy p = (Proxy) proxy; - return p.h; - } - - private static native Class defineClass0(ClassLoader loader, String name, - byte[] b, int off, int len); - - private static native Class<?> getPrecompiledProxy(ClassLoader loader, String proxyName, Class[] interfaces); -} diff --git a/openjdk/java/lang/reflect/ReflectHelper.java b/openjdk/java/lang/reflect/ReflectHelper.java deleted file mode 100644 index e0eb38cb..00000000 --- a/openjdk/java/lang/reflect/ReflectHelper.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - Copyright (C) 2007-2012 Jeroen Frijters - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jeroen Frijters - jeroen@frijters.net - -*/ - -package java.lang.reflect; - -@ikvm.lang.Internal -public final class ReflectHelper -{ - private ReflectHelper() {} - - public static Field copyFieldAndMakeAccessible(Field field) - { - field = field.copy(); - field.override = true; - return field; - } - - public static Field createFieldAndMakeAccessible(Class c, String name) - { - // we pass in ReflectHelper.class as the field type (which isn't used) - // to make Field.toString() return something "meaningful" instead of crash - Field field = new Field(c, name, ReflectHelper.class, 0, -1, null, null); - field.override = true; - return field; - } -} |