diff options
Diffstat (limited to 'libart/src/main/java')
19 files changed, 408 insertions, 818 deletions
diff --git a/libart/src/main/java/dalvik/system/TransactionAbortError.java b/libart/src/main/java/dalvik/system/TransactionAbortError.java new file mode 100644 index 0000000..cfe4ca2 --- /dev/null +++ b/libart/src/main/java/dalvik/system/TransactionAbortError.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dalvik.system; + +/** + * An exception only used by the compiler to abort a transaction. + * + * @hide + */ +final class TransactionAbortError extends InternalError { + /** + * Constructs a new {@code TransactionAbortError} with its stack trace filled in. + */ + private TransactionAbortError() { + } + + /** + * Constructs a new {@code TransactionAbortError} with its stack trace and detail + * message filled in. + * + * @param detailMessage the detail message for the exception. + */ + private TransactionAbortError(String detailMessage) { + super(detailMessage); + } + + /** + * Constructs a new {@code TransactionAbortError} with detail message and cause + * filled in. + * + * @param message the detail message for the exception. + * @param cause the detail cause for the exception. + */ + private TransactionAbortError(String message, Throwable cause) { + super(message); + initCause(cause); + } + + /** + * Constructs a new {@code TransactionAbortError} with its detail cause filled in. + * + * @param cause the detail cause for the exception. + */ + private TransactionAbortError(Throwable cause) { + this(cause == null ? null : cause.toString(), cause); + } + +} diff --git a/libart/src/main/java/dalvik/system/VMRuntime.java b/libart/src/main/java/dalvik/system/VMRuntime.java index 43fa00e..b885ed2 100644 --- a/libart/src/main/java/dalvik/system/VMRuntime.java +++ b/libart/src/main/java/dalvik/system/VMRuntime.java @@ -33,6 +33,10 @@ public final class VMRuntime { */ private static final VMRuntime THE_ONE = new VMRuntime(); + // Note: Instruction set names are used to construct the names of some + // system properties. To be sure that the properties stay valid the + // instruction set name should not exceed 7 characters. See installd + // and the package manager for the actual propeties. private static final Map<String, String> ABI_TO_INSTRUCTION_SET_MAP = new HashMap<String, String>(); static { @@ -272,6 +276,12 @@ public final class VMRuntime { public native void clearGrowthLimit(); /** + * Make the current growth limit the new non growth limit capacity by releasing pages which + * are after the growth limit but before the non growth limit capacity. + */ + public native void clampGrowthLimit(); + + /** * Returns true if either a Java debugger or native debugger is active. */ public native boolean isDebuggerActive(); @@ -291,8 +301,13 @@ public final class VMRuntime { */ public native void registerNativeFree(int bytes); - public native void trimHeap(); + public native void requestConcurrentGC(); public native void concurrentGC(); + public native void requestHeapTrim(); + public native void trimHeap(); + public native void startHeapTaskProcessor(); + public native void stopHeapTaskProcessor(); + public native void runHeapTasks(); /** * Let the heap know of the new process state. This can change allocation and garbage collection diff --git a/libart/src/main/java/dalvik/system/VMStack.java b/libart/src/main/java/dalvik/system/VMStack.java index ee0a0db..b69ab60 100644 --- a/libart/src/main/java/dalvik/system/VMStack.java +++ b/libart/src/main/java/dalvik/system/VMStack.java @@ -48,11 +48,10 @@ public final class VMStack { native public static Class<?> getStackClass2(); /** - * Returns the first ClassLoader on the call stack that isn't either of - * the passed-in ClassLoaders. + * Returns the first ClassLoader on the call stack that isn't the + * bootstrap class loader. */ - public native static ClassLoader getClosestUserClassLoader(ClassLoader bootstrap, - ClassLoader system); + public native static ClassLoader getClosestUserClassLoader(); /** * Retrieves the stack trace from the specified thread. diff --git a/libart/src/main/java/java/lang/Class.java b/libart/src/main/java/java/lang/Class.java index 8833776..99c562f 100644 --- a/libart/src/main/java/java/lang/Class.java +++ b/libart/src/main/java/java/lang/Class.java @@ -39,7 +39,6 @@ import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.reflect.AccessibleObject; import java.lang.reflect.AnnotatedElement; -import java.lang.reflect.ArtField; import java.lang.reflect.ArtMethod; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -55,6 +54,7 @@ import java.nio.charset.StandardCharsets; import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import libcore.reflect.AnnotationAccess; import libcore.reflect.GenericSignatureParser; @@ -124,16 +124,16 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe private static final long serialVersionUID = 3206093459760846163L; - /** defining class loader, or NULL for the "bootstrap" system loader. */ + /** defining class loader, or null for the "bootstrap" system loader. */ private transient ClassLoader classLoader; /** * For array classes, the component class object for instanceof/checkcast (for String[][][], - * this will be String[][]). NULL for non-array classes. + * this will be String[][]). null for non-array classes. */ private transient Class<?> componentType; /** - * DexCache of resolved constant pool entries. Will be null for certain VM-generated classes + * DexCache of resolved constant pool entries. Will be null for certain runtime-generated classes * e.g. arrays and primitive classes. */ private transient DexCache dexCache; @@ -145,16 +145,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe private transient ArtMethod[] directMethods; /** - * Instance fields. These describe the layout of the contents of an Object. Note that only the - * fields directly declared by this class are listed in iFields; fields declared by a - * superclass are listed in the superclass's Class.iFields. - * - * All instance fields that refer to objects are guaranteed to be at the beginning of the field - * list. {@link Class#numReferenceInstanceFields} specifies the number of reference fields. - */ - private transient ArtField[] iFields; - - /** * The interface table (iftable_) contains pairs of a interface class and an array of the * interface methods. There is one pair per interface supported by this class. That * means one pair for each interface we support directly, indirectly via superclass, or @@ -173,10 +163,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe /** Lazily computed name of this class; always prefer calling getName(). */ private transient String name; - /** Static fields */ - private transient ArtField[] sFields; - - /** The superclass, or NULL if this is java.lang.Object, an interface or primitive type. */ + /** The superclass, or null if this is java.lang.Object, an interface or primitive type. */ private transient Class<? super T> superClass; /** If class verify fails, we must return same error on subsequent tries. */ @@ -197,6 +184,20 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe private transient int accessFlags; /** + * Instance fields. These describe the layout of the contents of an Object. Note that only the + * fields directly declared by this class are listed in iFields; fields declared by a + * superclass are listed in the superclass's Class.iFields. + * + * All instance fields that refer to objects are guaranteed to be at the beginning of the field + * list. {@link Class#numReferenceInstanceFields} specifies the number of reference fields. + */ + private transient long iFields; + + /** Static fields */ + private transient long sFields; + + + /** * Total size of the Class instance; used when allocating storage on GC heap. * See also {@link Class#objectSize}. */ @@ -221,32 +222,39 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe */ private transient volatile int dexTypeIndex; + /** Number of instance fields. */ + private transient int numInstanceFields; + /** Number of instance fields that are object references. */ private transient int numReferenceInstanceFields; /** Number of static fields that are object references. */ private transient int numReferenceStaticFields; + /** Number of static fields. */ + private transient int numStaticFields; + /** * Total object size; used when allocating storage on GC heap. For interfaces and abstract * classes this will be zero. See also {@link Class#classSize}. */ private transient int objectSize; - /** Primitive type value, or 0 if not a primitive type; set for generated primitive classes. */ + /** + * The lower 16 bits is the primitive type value, or 0 if not a primitive type; set for + * generated primitive classes. + */ private transient int primitiveType; /** Bitmap of offsets of iFields. */ private transient int referenceInstanceOffsets; - /** Bitmap of offsets of sFields. */ - private transient int referenceStaticOffsets; - /** State of class initialization */ private transient int status; private Class() { - // Prevent this class to be instantiated, instance should be created by JVM only + // Prevent this class from being instantiated, + // instances should be created by the runtime only. } /** @@ -284,6 +292,9 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * If the class has not yet been initialized and {@code shouldInitialize} is true, * the class will be initialized. * + * <p>If the provided {@code classLoader} is {@code null}, the bootstrap + * class loader will be used to load the class. + * * @throws ClassNotFoundException * if the requested class cannot be found. * @throws LinkageError @@ -296,7 +307,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe ClassLoader classLoader) throws ClassNotFoundException { if (classLoader == null) { - classLoader = ClassLoader.getSystemClassLoader(); + classLoader = BootClassLoader.getInstance(); } // Catch an Exception thrown by the underlying native code. It wraps // up everything inside a ClassNotFoundException, even if e.g. an @@ -407,24 +418,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe return null; } - ClassLoader loader = getClassLoaderImpl(); - if (loader == null) { - loader = BootClassLoader.getInstance(); - } - return loader; - } - - /** - * This must be provided by the VM vendor, as it is used by other provided - * class implementations in this package. Outside of this class, it is used - * by SecurityManager.classLoaderDepth(), - * currentClassLoader() and currentLoadedClass(). Return the ClassLoader for - * this Class without doing any security checks. The bootstrap ClassLoader - * is returned, unlike getClassLoader() which returns null in place of the - * bootstrap ClassLoader. - */ - ClassLoader getClassLoaderImpl() { - ClassLoader loader = classLoader; + final ClassLoader loader = classLoader; return loader == null ? BootClassLoader.getInstance() : loader; } @@ -456,10 +450,10 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @hide */ public String getDexCacheString(Dex dex, int dexStringIndex) { - String s = dexCacheStrings[dexStringIndex]; + String s = dexCache.getResolvedString(dexStringIndex); if (s == null) { s = dex.strings().get(dexStringIndex).intern(); - dexCacheStrings[dexStringIndex] = s; + dexCache.setResolvedString(dexStringIndex, s); } return s; } @@ -471,13 +465,12 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @hide */ public Class<?> getDexCacheType(Dex dex, int dexTypeIndex) { - Class<?>[] dexCacheResolvedTypes = dexCache.resolvedTypes; - Class<?> resolvedType = dexCacheResolvedTypes[dexTypeIndex]; + Class<?> resolvedType = dexCache.getResolvedType(dexTypeIndex); if (resolvedType == null) { int descriptorIndex = dex.typeIds().get(dexTypeIndex); String descriptor = getDexCacheString(dex, descriptorIndex); resolvedType = InternalNames.getClass(getClassLoader(), descriptor); - dexCacheResolvedTypes[dexTypeIndex] = resolvedType; + dexCache.setResolvedType(dexTypeIndex, resolvedType); } return resolvedType; } @@ -534,30 +527,12 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns the constructor with the given parameters if it is defined by this class; null - * otherwise. This may return a non-public member. + * Returns the constructor with the given parameters if it is defined by this class; + * {@code null} otherwise. This may return a non-public member. * * @param args the types of the parameters to the constructor. */ - private Constructor<T> getDeclaredConstructorInternal(Class<?>[] args) { - if (directMethods != null) { - for (ArtMethod m : directMethods) { - int modifiers = m.getAccessFlags(); - if (Modifier.isStatic(modifiers)) { - // skip <clinit> which is a static constructor - continue; - } - if (!Modifier.isConstructor(modifiers)) { - continue; - } - if (!ArtMethod.equalConstructorParameters(m, args)) { - continue; - } - return new Constructor<T>(m); - } - } - return null; - } + private native Constructor<T> getDeclaredConstructorInternal(Class<?>[] args); /** * Returns an array containing {@code Constructor} objects for all public @@ -568,9 +543,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @see #getDeclaredConstructors() */ public Constructor<?>[] getConstructors() { - ArrayList<Constructor<T>> constructors = new ArrayList(); - getDeclaredConstructors(true, constructors); - return constructors.toArray(new Constructor[constructors.size()]); + return getDeclaredConstructorsInternal(true); } /** @@ -582,28 +555,11 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @see #getConstructors() */ public Constructor<?>[] getDeclaredConstructors() { - ArrayList<Constructor<T>> constructors = new ArrayList(); - getDeclaredConstructors(false, constructors); - return constructors.toArray(new Constructor[constructors.size()]); - } - - private void getDeclaredConstructors(boolean publicOnly, List<Constructor<T>> constructors) { - if (directMethods != null) { - for (ArtMethod m : directMethods) { - int modifiers = m.getAccessFlags(); - if (!publicOnly || Modifier.isPublic(modifiers)) { - if (Modifier.isStatic(modifiers)) { - // skip <clinit> which is a static constructor - continue; - } - if (Modifier.isConstructor(modifiers)) { - constructors.add(new Constructor<T>(m)); - } - } - } - } + return getDeclaredConstructorsInternal(false); } + private native Constructor<?>[] getDeclaredConstructorsInternal(boolean publicOnly); + /** * Returns a {@code Method} object which represents the method matching the * specified name and parameter types that is declared by the class @@ -689,68 +645,13 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns the method if it is defined by this class; null otherwise. This may return a + * Returns the method if it is defined by this class; {@code null} otherwise. This may return a * non-public member. * * @param name the method name * @param args the method's parameter types */ - private Method getDeclaredMethodInternal(String name, Class<?>[] args) { - // Covariant return types permit the class to define multiple - // methods with the same name and parameter types. Prefer to - // return a non-synthetic method in such situations. We may - // still return a synthetic method to handle situations like - // escalated visibility. We never return miranda methods that - // were synthesized by the VM. - int skipModifiers = Modifier.MIRANDA | Modifier.SYNTHETIC; - ArtMethod artMethodResult = null; - if (virtualMethods != null) { - for (ArtMethod m : virtualMethods) { - String methodName = ArtMethod.getMethodName(m); - if (!name.equals(methodName)) { - continue; - } - if (!ArtMethod.equalMethodParameters(m, args)) { - continue; - } - int modifiers = m.getAccessFlags(); - if ((modifiers & skipModifiers) == 0) { - return new Method(m); - } - if ((modifiers & Modifier.MIRANDA) == 0) { - // Remember as potential result if it's not a miranda method. - artMethodResult = m; - } - } - } - if (artMethodResult == null) { - if (directMethods != null) { - for (ArtMethod m : directMethods) { - int modifiers = m.getAccessFlags(); - if (Modifier.isConstructor(modifiers)) { - continue; - } - String methodName = ArtMethod.getMethodName(m); - if (!name.equals(methodName)) { - continue; - } - if (!ArtMethod.equalMethodParameters(m, args)) { - continue; - } - if ((modifiers & skipModifiers) == 0) { - return new Method(m); - } - // Direct methods cannot be miranda methods, - // so this potential result must be synthetic. - artMethodResult = m; - } - } - } - if (artMethodResult == null) { - return null; - } - return new Method(artMethodResult); - } + private native Method getDeclaredMethodInternal(String name, Class<?>[] args); /** * Returns an array containing {@code Method} objects for all methods @@ -761,11 +662,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @see #getMethods() */ public Method[] getDeclaredMethods() { - int initial_size = virtualMethods == null ? 0 : virtualMethods.length; - initial_size += directMethods == null ? 0 : directMethods.length; - ArrayList<Method> methods = new ArrayList<Method>(initial_size); - getDeclaredMethodsUnchecked(false, methods); - Method[] result = methods.toArray(new Method[methods.size()]); + Method[] result = getDeclaredMethodsUnchecked(false); for (Method m : result) { // Throw NoClassDefFoundError if types cannot be resolved. m.getReturnType(); @@ -783,30 +680,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @param methods A list to populate with declared methods. * @hide */ - public void getDeclaredMethodsUnchecked(boolean publicOnly, List<Method> methods) { - if (virtualMethods != null) { - for (ArtMethod m : virtualMethods) { - int modifiers = m.getAccessFlags(); - if (!publicOnly || Modifier.isPublic(modifiers)) { - // Add non-miranda virtual methods. - if ((modifiers & Modifier.MIRANDA) == 0) { - methods.add(new Method(m)); - } - } - } - } - if (directMethods != null) { - for (ArtMethod m : directMethods) { - int modifiers = m.getAccessFlags(); - if (!publicOnly || Modifier.isPublic(modifiers)) { - // Add non-constructor direct/static methods. - if (!Modifier.isConstructor(modifiers)) { - methods.add(new Method(m)); - } - } - } - } - } + public native Method[] getDeclaredMethodsUnchecked(boolean publicOnly); /** * Returns an array containing {@code Method} objects for all public methods @@ -836,11 +710,11 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * superclasses, and all implemented interfaces, including overridden methods. */ private void getPublicMethodsInternal(List<Method> result) { - getDeclaredMethodsUnchecked(true, result); + Collections.addAll(result, getDeclaredMethodsUnchecked(true)); if (!isInterface()) { // Search superclasses, for interfaces don't search java.lang.Object. for (Class<?> c = superClass; c != null; c = c.superClass) { - c.getDeclaredMethodsUnchecked(true, result); + Collections.addAll(result, c.getDeclaredMethodsUnchecked(true)); } } // Search iftable which has a flattened and uniqued list of interfaces. @@ -848,7 +722,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe if (iftable != null) { for (int i = 0; i < iftable.length; i += 2) { Class<?> ifc = (Class<?>) iftable[i]; - ifc.getDeclaredMethodsUnchecked(true, result); + Collections.addAll(result, ifc.getDeclaredMethodsUnchecked(true)); } } } @@ -881,18 +755,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @throws NoSuchFieldException if the requested field can not be found. * @see #getField(String) */ - public Field getDeclaredField(String name) throws NoSuchFieldException { - if (name == null) { - throw new NullPointerException("name == null"); - } - Field result = getDeclaredFieldInternal(name); - if (result == null) { - throw new NoSuchFieldException(name); - } else { - result.getType(); // Throw NoClassDefFoundError if type cannot be resolved. - } - return result; - } + public native Field getDeclaredField(String name) throws NoSuchFieldException; /** * Returns an array containing {@code Field} objects for all fields declared @@ -902,17 +765,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * * @see #getFields() */ - public Field[] getDeclaredFields() { - int initial_size = sFields == null ? 0 : sFields.length; - initial_size += iFields == null ? 0 : iFields.length; - ArrayList<Field> fields = new ArrayList(initial_size); - getDeclaredFieldsUnchecked(false, fields); - Field[] result = fields.toArray(new Field[fields.size()]); - for (Field f : result) { - f.getType(); // Throw NoClassDefFoundError if type cannot be resolved. - } - return result; - } + public native Field[] getDeclaredFields(); /** * Populates a list of fields without performing any security or type @@ -922,66 +775,18 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @param fields A list to populate with declared fields. * @hide */ - public void getDeclaredFieldsUnchecked(boolean publicOnly, List<Field> fields) { - if (iFields != null) { - for (ArtField f : iFields) { - if (!publicOnly || Modifier.isPublic(f.getAccessFlags())) { - fields.add(new Field(f)); - } - } - } - if (sFields != null) { - for (ArtField f : sFields) { - if (!publicOnly || Modifier.isPublic(f.getAccessFlags())) { - fields.add(new Field(f)); - } - } - } - } + public native Field[] getDeclaredFieldsUnchecked(boolean publicOnly); /** - * Returns the field if it is defined by this class; null otherwise. This + * Returns the field if it is defined by this class; {@code null} otherwise. This * may return a non-public member. */ - private Field getDeclaredFieldInternal(String name) { - - if (iFields != null) { - final ArtField matched = findByName(name, iFields); - if (matched != null) { - return new Field(matched); - } - } - if (sFields != null) { - final ArtField matched = findByName(name, sFields); - if (matched != null) { - return new Field(matched); - } - } - - return null; - } + private native Field getDeclaredFieldInternal(String name); /** - * Performs a binary search through {@code fields} for a field whose name - * is {@code name}. Returns {@code null} if no matching field exists. + * Returns the subset of getDeclaredFields which are public. */ - private static ArtField findByName(String name, ArtField[] fields) { - int low = 0, high = fields.length - 1; - while (low <= high) { - final int mid = (low + high) >>> 1; - final ArtField f = fields[mid]; - final int result = f.getName().compareTo(name); - if (result < 0) { - low = mid + 1; - } else if (result == 0) { - return f; - } else { - high = mid - 1; - } - } - - return null; - } + private native Field[] getPublicDeclaredFields(); /** * Returns the class that this class is a member of, or {@code null} if this @@ -1080,8 +885,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe Field result = getPublicFieldRecursive(name); if (result == null) { throw new NoSuchFieldException(name); - } else { - result.getType(); // Throw NoClassDefFoundError if type cannot be resolved. } return result; } @@ -1098,8 +901,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe // search iftable which has a flattened and uniqued list of interfaces if (ifTable != null) { for (int i = 0; i < ifTable.length; i += 2) { - Class<?> ifc = (Class<?>) ifTable[i]; - Field result = ifc.getPublicFieldRecursive(name); + Field result = ((Class<?>) ifTable[i]).getPublicFieldRecursive(name); if (result != null && (result.getModifiers() & Modifier.PUBLIC) != 0) { return result; } @@ -1123,11 +925,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe public Field[] getFields() { List<Field> fields = new ArrayList<Field>(); getPublicFieldsRecursive(fields); - Field[] result = fields.toArray(new Field[fields.size()]); - for (Field f : result) { - f.getType(); // Throw NoClassDefFoundError if type cannot be resolved. - } - return result; + return fields.toArray(new Field[fields.size()]); } /** @@ -1137,15 +935,14 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe private void getPublicFieldsRecursive(List<Field> result) { // search superclasses for (Class<?> c = this; c != null; c = c.superClass) { - c.getDeclaredFieldsUnchecked(true, result); + Collections.addAll(result, c.getPublicDeclaredFields()); } // search iftable which has a flattened and uniqued list of interfaces Object[] iftable = ifTable; if (iftable != null) { for (int i = 0; i < iftable.length; i += 2) { - Class<?> ifc = (Class<?>) iftable[i]; - ifc.getDeclaredFieldsUnchecked(true, result); + Collections.addAll(result, ((Class<?>) iftable[i]).getPublicDeclaredFields()); } } } @@ -1295,21 +1092,21 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns the simple name of a member or local class, or null otherwise. + * Returns the simple name of a member or local class, or {@code null} otherwise. */ private String getInnerClassName() { return AnnotationAccess.getInnerClassName(this); } /** - * Returns null. + * Returns {@code null}. */ public ProtectionDomain getProtectionDomain() { return null; } /** - * Returns the URL of the given resource, or null if the resource is not found. + * Returns the URL of the given resource, or {@code null} if the resource is not found. * The mapping between the resource name and the URL is managed by the class' class loader. * * @see ClassLoader @@ -1340,8 +1137,8 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns a read-only stream for the contents of the given resource, or null if the resource - * is not found. + * Returns a read-only stream for the contents of the given resource, or {@code null} if the + * resource is not found. * The mapping between the resource name and the stream is managed by the class' class loader. * * @see ClassLoader @@ -1372,8 +1169,8 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns null. (On Android, a {@code ClassLoader} can load classes from multiple dex files. - * All classes from any given dex file will have the same signers, but different dex + * Returns {@code null}. (On Android, a {@code ClassLoader} can load classes from multiple dex + * files. All classes from any given dex file will have the same signers, but different dex * files may have different signers. This does not fit well with the original * {@code ClassLoader}-based model of {@code getSigners}.) */ @@ -1547,7 +1344,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * Tests whether this {@code Class} represents a primitive type. */ public boolean isPrimitive() { - return primitiveType != 0; + return (primitiveType & 0xFFFF) != 0; } /** @@ -1582,33 +1379,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @throws InstantiationException * if the instance cannot be created. */ - public T newInstance() throws InstantiationException, IllegalAccessException { - if (isPrimitive() || isInterface() || isArray() || Modifier.isAbstract(accessFlags)) { - throw new InstantiationException(this + " cannot be instantiated"); - } - Class<?> caller = VMStack.getStackClass1(); - if (!caller.canAccess(this)) { - throw new IllegalAccessException(this + " is not accessible from " + caller); - } - Constructor<T> init; - try { - init = getDeclaredConstructor(); - } catch (NoSuchMethodException e) { - InstantiationException t = - new InstantiationException(this + " has no zero argument constructor"); - t.initCause(e); - throw t; - } - if (!caller.canAccessMember(this, init.getAccessFlags())) { - throw new IllegalAccessException(init + " is not accessible from " + caller); - } - try { - return init.newInstance(null, init.isAccessible()); - } catch (InvocationTargetException e) { - SneakyThrow.sneakyThrow(e.getCause()); - return null; // Unreachable. - } - } + public native T newInstance() throws InstantiationException, IllegalAccessException; private boolean canAccess(Class<?> c) { if(Modifier.isPublic(c.accessFlags)) { @@ -1664,7 +1435,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * object was created by the class loader of the class. */ public Package getPackage() { - // TODO This might be a hack, but the VM doesn't have the necessary info. + // TODO This might be a hack, but the runtime doesn't have the necessary info. ClassLoader loader = getClassLoader(); if (loader != null) { String packageName = getPackageName$(); @@ -1674,7 +1445,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns the package name of this class. This returns null for classes in + * Returns the package name of this class. This returns {@code null} for classes in * the default package. * * @hide diff --git a/libart/src/main/java/java/lang/ClassLoader.java b/libart/src/main/java/java/lang/ClassLoader.java index 9079dc4..dfbeeb5 100644 --- a/libart/src/main/java/java/lang/ClassLoader.java +++ b/libart/src/main/java/java/lang/ClassLoader.java @@ -646,8 +646,8 @@ public abstract class ClassLoader { throw new IllegalArgumentException("Package " + name + " already defined"); } - Package newPackage = new Package(name, specTitle, specVersion, specVendor, implTitle, - implVersion, implVendor, sealBase); + Package newPackage = new Package(this, name, specTitle, specVersion, specVendor, + implTitle, implVersion, implVendor, sealBase); packages.put(name, newPackage); diff --git a/libart/src/main/java/java/lang/Daemons.java b/libart/src/main/java/java/lang/Daemons.java index 485f2c9..43066e1 100644 --- a/libart/src/main/java/java/lang/Daemons.java +++ b/libart/src/main/java/java/lang/Daemons.java @@ -40,16 +40,14 @@ public final class Daemons { ReferenceQueueDaemon.INSTANCE.start(); FinalizerDaemon.INSTANCE.start(); FinalizerWatchdogDaemon.INSTANCE.start(); - HeapTrimmerDaemon.INSTANCE.start(); - GCDaemon.INSTANCE.start(); + HeapTaskDaemon.INSTANCE.start(); } public static void stop() { + HeapTaskDaemon.INSTANCE.stop(); ReferenceQueueDaemon.INSTANCE.stop(); FinalizerDaemon.INSTANCE.stop(); FinalizerWatchdogDaemon.INSTANCE.stop(); - HeapTrimmerDaemon.INSTANCE.stop(); - GCDaemon.INSTANCE.stop(); } /** @@ -59,12 +57,17 @@ public final class Daemons { */ private static abstract class Daemon implements Runnable { private Thread thread; + private String name; + + protected Daemon(String name) { + this.name = name; + } public synchronized void start() { if (thread != null) { throw new IllegalStateException("already running"); } - thread = new Thread(ThreadGroup.systemThreadGroup, this, getClass().getSimpleName()); + thread = new Thread(ThreadGroup.systemThreadGroup, this, name); thread.setDaemon(true); thread.start(); } @@ -80,6 +83,10 @@ public final class Daemons { } public synchronized void interrupt() { + interrupt(thread); + } + + public synchronized void interrupt(Thread thread) { if (thread == null) { throw new IllegalStateException("not running"); } @@ -99,7 +106,7 @@ public final class Daemons { if (threadToStop == null) { throw new IllegalStateException("not running"); } - threadToStop.interrupt(); + interrupt(threadToStop); while (true) { try { threadToStop.join(); @@ -125,6 +132,10 @@ public final class Daemons { private static class ReferenceQueueDaemon extends Daemon { private static final ReferenceQueueDaemon INSTANCE = new ReferenceQueueDaemon(); + ReferenceQueueDaemon() { + super("ReferenceQueueDaemon"); + } + @Override public void run() { while (isRunning()) { Reference<?> list; @@ -144,20 +155,14 @@ public final class Daemons { } private void enqueue(Reference<?> list) { - while (list != null) { - Reference<?> reference; - // pendingNext is owned by the GC so no synchronization is required - if (list == list.pendingNext) { - reference = list; - reference.pendingNext = null; - list = null; - } else { - reference = list.pendingNext; - list.pendingNext = reference.pendingNext; - reference.pendingNext = null; - } - reference.enqueueInternal(); - } + Reference<?> start = list; + do { + // pendingNext is owned by the GC so no synchronization is required. + Reference<?> next = list.pendingNext; + list.pendingNext = null; + list.enqueueInternal(); + list = next; + } while (list != start); } } @@ -167,6 +172,10 @@ public final class Daemons { private volatile Object finalizingObject; private volatile long finalizingStartedNanos; + FinalizerDaemon() { + super("FinalizerDaemon"); + } + @Override public void run() { while (isRunning()) { // Take a reference, blocking until one is ready or the thread should stop @@ -207,6 +216,10 @@ public final class Daemons { private static class FinalizerWatchdogDaemon extends Daemon { private static final FinalizerWatchdogDaemon INSTANCE = new FinalizerWatchdogDaemon(); + FinalizerWatchdogDaemon() { + super("FinalizerWatchdogDaemon"); + } + @Override public void run() { while (isRunning()) { boolean waitSuccessful = waitForObject(); @@ -294,59 +307,42 @@ public final class Daemons { } } - // Invoked by the GC to request that the HeapTrimmerDaemon thread attempt to trim the heap. + // Adds a heap trim task ot the heap event processor, not called from java. Left for + // compatibility purposes due to reflection. public static void requestHeapTrim() { - synchronized (HeapTrimmerDaemon.INSTANCE) { - HeapTrimmerDaemon.INSTANCE.notify(); - } - } - - private static class HeapTrimmerDaemon extends Daemon { - private static final HeapTrimmerDaemon INSTANCE = new HeapTrimmerDaemon(); - - @Override public void run() { - while (isRunning()) { - try { - synchronized (this) { - wait(); - } - VMRuntime.getRuntime().trimHeap(); - } catch (InterruptedException ignored) { - } - } - } + VMRuntime.getRuntime().requestHeapTrim(); } - // Invoked by the GC to request that the HeapTrimmerDaemon thread attempt to trim the heap. + // Adds a concurrent GC request task ot the heap event processor, not called from java. Left + // for compatibility purposes due to reflection. public static void requestGC() { - GCDaemon.INSTANCE.requestGC(); + VMRuntime.getRuntime().requestConcurrentGC(); } - private static class GCDaemon extends Daemon { - private static final GCDaemon INSTANCE = new GCDaemon(); - private static final AtomicBoolean atomicBoolean = new AtomicBoolean(); + private static class HeapTaskDaemon extends Daemon { + private static final HeapTaskDaemon INSTANCE = new HeapTaskDaemon(); - public void requestGC() { - if (atomicBoolean.getAndSet(true)) { - return; - } - synchronized (this) { - notify(); - } - atomicBoolean.set(false); + HeapTaskDaemon() { + super("HeapTaskDaemon"); + } + + // Overrides the Daemon.interupt method which is called from Daemons.stop. + public synchronized void interrupt(Thread thread) { + VMRuntime.getRuntime().stopHeapTaskProcessor(); } @Override public void run() { - while (isRunning()) { - try { - synchronized (this) { - // Wait until a request comes in. - wait(); - } - VMRuntime.getRuntime().concurrentGC(); - } catch (InterruptedException ignored) { + synchronized (this) { + if (isRunning()) { + // Needs to be synchronized or else we there is a race condition where we start + // the thread, call stopHeapTaskProcessor before we start the heap task + // processor, resulting in a deadlock since startHeapTaskProcessor restarts it + // while the other thread is waiting in Daemons.stop(). + VMRuntime.getRuntime().startHeapTaskProcessor(); } } + // This runs tasks until we are stopped and there is no more pending task. + VMRuntime.getRuntime().runHeapTasks(); } } } diff --git a/libart/src/main/java/java/lang/DexCache.java b/libart/src/main/java/java/lang/DexCache.java index e4caffa..c047018 100644 --- a/libart/src/main/java/java/lang/DexCache.java +++ b/libart/src/main/java/java/lang/DexCache.java @@ -33,7 +33,6 @@ package java.lang; import com.android.dex.Dex; -import java.lang.reflect.ArtField; import java.lang.reflect.ArtMethod; /** @@ -47,18 +46,18 @@ final class DexCache { String location; /** - * References to fields as they become resolved following interpreter semantics. May refer to - * fields defined in other dex files. - */ - ArtField[] resolvedFields; - - /** * References to methods as they become resolved following interpreter semantics. May refer to * methods defined in other dex files. */ ArtMethod[] resolvedMethods; /** + * References to fields as they become resolved following interpreter semantics. May refer to + * fields defined in other dex files. Either an int array or long array. + */ + private Object resolvedFields; + + /** * References to types as they become resolved following interpreter semantics. May refer to * types defined in other dex files. */ @@ -89,6 +88,10 @@ final class DexCache { return result; } + native Class<?> getResolvedType(int typeIndex); + native String getResolvedString(int stringIndex); + native void setResolvedType(int typeIndex, Class<?> type); + native void setResolvedString(int stringIndex, String string); private native Dex getDexNative(); } diff --git a/libart/src/main/java/java/lang/Object.java b/libart/src/main/java/java/lang/Object.java index 20fdbf9..5b820e3 100644 --- a/libart/src/main/java/java/lang/Object.java +++ b/libart/src/main/java/java/lang/Object.java @@ -274,10 +274,11 @@ public class Object { */ public int hashCode() { int lockWord = shadow$_monitor_; - final int lockWordMask = 0xC0000000; // Top 2 bits. + final int lockWordStateMask = 0xC0000000; // Top 2 bits. final int lockWordStateHash = 0x80000000; // Top 2 bits are value 2 (kStateHash). - if ((lockWord & lockWordMask) == lockWordStateHash) { - return lockWord & ~lockWordMask; + final int lockWordHashMask = 0x0FFFFFFF; // Low 28 bits. + if ((lockWord & lockWordStateMask) == lockWordStateHash) { + return lockWord & lockWordHashMask; } return System.identityHashCode(this); } diff --git a/libart/src/main/java/java/lang/String.java b/libart/src/main/java/java/lang/String.java index 0107b6e..a5bf34c 100644 --- a/libart/src/main/java/java/lang/String.java +++ b/libart/src/main/java/java/lang/String.java @@ -22,12 +22,12 @@ import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; -import java.nio.charset.Charsets; import java.util.Arrays; import java.util.Comparator; import java.util.Formatter; import java.util.Locale; import java.util.regex.Pattern; +import libcore.util.CharsetUtils; import libcore.util.EmptyArray; /** @@ -337,12 +337,12 @@ outer: this.offset = 0; this.value = new char[byteCount]; this.count = byteCount; - Charsets.isoLatin1BytesToChars(data, offset, byteCount, value); + CharsetUtils.isoLatin1BytesToChars(data, offset, byteCount, value); } else if (canonicalCharsetName.equals("US-ASCII")) { this.offset = 0; this.value = new char[byteCount]; this.count = byteCount; - Charsets.asciiBytesToChars(data, offset, byteCount, value); + CharsetUtils.asciiBytesToChars(data, offset, byteCount, value); } else { CharBuffer cb = charset.decode(ByteBuffer.wrap(data, offset, byteCount)); this.offset = 0; @@ -772,13 +772,13 @@ outer: public byte[] getBytes(Charset charset) { String canonicalCharsetName = charset.name(); if (canonicalCharsetName.equals("UTF-8")) { - return Charsets.toUtf8Bytes(value, offset, count); + return CharsetUtils.toUtf8Bytes(value, offset, count); } else if (canonicalCharsetName.equals("ISO-8859-1")) { - return Charsets.toIsoLatin1Bytes(value, offset, count); + return CharsetUtils.toIsoLatin1Bytes(value, offset, count); } else if (canonicalCharsetName.equals("US-ASCII")) { - return Charsets.toAsciiBytes(value, offset, count); + return CharsetUtils.toAsciiBytes(value, offset, count); } else if (canonicalCharsetName.equals("UTF-16BE")) { - return Charsets.toBigEndianUtf16Bytes(value, offset, count); + return CharsetUtils.toBigEndianUtf16Bytes(value, offset, count); } else { CharBuffer chars = CharBuffer.wrap(this.value, this.offset, this.count); ByteBuffer buffer = charset.encode(chars.asReadOnlyBuffer()); diff --git a/libart/src/main/java/java/lang/Thread.java b/libart/src/main/java/java/lang/Thread.java index 852e2cf..7b3666b 100644 --- a/libart/src/main/java/java/lang/Thread.java +++ b/libart/src/main/java/java/lang/Thread.java @@ -1158,7 +1158,7 @@ public class Thread implements Runnable { * * @hide for Unsafe */ - public void unpark() { + public final void unpark$() { synchronized (lock) { switch (parkState) { case ParkState.PREEMPTIVELY_UNPARKED: { @@ -1204,7 +1204,7 @@ public class Thread implements Runnable { * * @hide for Unsafe */ - public void parkFor(long nanos) { + public final void parkFor$(long nanos) { synchronized (lock) { switch (parkState) { case ParkState.PREEMPTIVELY_UNPARKED: { @@ -1260,7 +1260,7 @@ public class Thread implements Runnable { * * @hide for Unsafe */ - public void parkUntil(long time) { + public final void parkUntil$(long time) { synchronized (lock) { /* * Note: This conflates the two time bases of "wall clock" @@ -1281,7 +1281,7 @@ public class Thread implements Runnable { if (delayMillis <= 0) { parkState = ParkState.UNPARKED; } else { - parkFor(delayMillis * NANOS_PER_MILLI); + parkFor$(delayMillis * NANOS_PER_MILLI); } } } diff --git a/libart/src/main/java/java/lang/reflect/AbstractMethod.java b/libart/src/main/java/java/lang/reflect/AbstractMethod.java index 7e6491d..0ac15f9 100644 --- a/libart/src/main/java/java/lang/reflect/AbstractMethod.java +++ b/libart/src/main/java/java/lang/reflect/AbstractMethod.java @@ -39,28 +39,38 @@ import libcore.reflect.AnnotationAccess; import libcore.reflect.GenericSignatureParser; import libcore.reflect.ListOfTypes; import libcore.reflect.Types; +import libcore.util.EmptyArray; /** * This class represents an abstract method. Abstract methods are either methods or constructors. * @hide */ public abstract class AbstractMethod extends AccessibleObject { + /** Bits encoding access (e.g. public, private) as well as other runtime specific flags */ + protected int accessFlags; /** + * The ArtMethod associated with this Method, requried for dispatching due to entrypoints * Hidden to workaround b/16828157. * @hide */ - protected final ArtMethod artMethod; + protected ArtMethod artMethod; + + /** Method's declaring class */ + protected Class<?> declaringClass; + + /** Overriden method's declaring class (same as declaringClass unless declaringClass + * is a proxy class) */ + protected Class<?> declaringClassOfOverriddenMethod; + + /** The method index of this method within its defining dex file */ + protected int dexMethodIndex; /** * Hidden to workaround b/16828157. * @hide */ - protected AbstractMethod(ArtMethod artMethod) { - if (artMethod == null) { - throw new NullPointerException("artMethod == null"); - } - this.artMethod = artMethod; + protected AbstractMethod() { } public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { @@ -90,33 +100,33 @@ public abstract class AbstractMethod extends AccessibleObject { } int getModifiers() { - return fixMethodFlags(artMethod.getAccessFlags()); + return fixMethodFlags(accessFlags); } boolean isVarArgs() { - return (artMethod.getAccessFlags() & Modifier.VARARGS) != 0; + return (accessFlags & Modifier.VARARGS) != 0; } boolean isBridge() { - return (artMethod.getAccessFlags() & Modifier.BRIDGE) != 0; + return (accessFlags & Modifier.BRIDGE) != 0; } boolean isSynthetic() { - return (artMethod.getAccessFlags() & Modifier.SYNTHETIC) != 0; + return (accessFlags & Modifier.SYNTHETIC) != 0; } /** * @hide */ public final int getAccessFlags() { - return artMethod.getAccessFlags(); + return accessFlags; } /** * Returns the class that declares this constructor or method. */ Class<?> getDeclaringClass() { - return artMethod.getDeclaringClass(); + return declaringClass; } /** @@ -125,7 +135,7 @@ public abstract class AbstractMethod extends AccessibleObject { * @hide */ public final int getDexMethodIndex() { - return artMethod.getDexMethodIndex(); + return dexMethodIndex; } /** @@ -144,7 +154,17 @@ public abstract class AbstractMethod extends AccessibleObject { * @return the parameter types */ Class<?>[] getParameterTypes() { - return artMethod.getParameterTypes(); + Dex dex = declaringClassOfOverriddenMethod.getDex(); + short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex); + if (types.length == 0) { + return EmptyArray.CLASS; + } + Class<?>[] parametersArray = new Class[types.length]; + for (int i = 0; i < types.length; i++) { + // Note, in the case of a Proxy the dex cache types are equal. + parametersArray[i] = declaringClassOfOverriddenMethod.getDexCacheType(dex, types[i]); + } + return parametersArray; } /** @@ -155,8 +175,10 @@ public abstract class AbstractMethod extends AccessibleObject { if (!(other instanceof AbstractMethod)) { return false; } - // exactly one instance of each member in this runtime - return this.artMethod == ((AbstractMethod) other).artMethod; + // Exactly one instance of each member in this runtime, todo, does this work for proxies? + AbstractMethod otherMethod = (AbstractMethod) other; + return this.declaringClass == otherMethod.declaringClass && + this.dexMethodIndex == otherMethod.dexMethodIndex; } String toGenericString() { @@ -252,6 +274,37 @@ public abstract class AbstractMethod extends AccessibleObject { parser.returnType, parser.formalTypeParameters); } + protected boolean equalMethodParameters(Class<?>[] params) { + Dex dex = declaringClassOfOverriddenMethod.getDex(); + short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex); + if (types.length != params.length) { + return false; + } + for (int i = 0; i < types.length; i++) { + if (declaringClassOfOverriddenMethod.getDexCacheType(dex, types[i]) != params[i]) { + return false; + } + } + return true; + } + + protected int compareParameters(Class<?>[] params) { + Dex dex = declaringClassOfOverriddenMethod.getDex(); + short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex); + int length = Math.min(types.length, params.length); + for (int i = 0; i < length; i++) { + Class<?> aType = declaringClassOfOverriddenMethod.getDexCacheType(dex, types[i]); + Class<?> bType = params[i]; + if (aType != bType) { + int comparison = aType.getName().compareTo(bType.getName()); + if (comparison != 0) { + return comparison; + } + } + } + return types.length - params.length; + } + /** * Helper for Method and Constructor for toGenericString */ diff --git a/libart/src/main/java/java/lang/reflect/AccessibleObject.java b/libart/src/main/java/java/lang/reflect/AccessibleObject.java index a1e2743..f623880 100644 --- a/libart/src/main/java/java/lang/reflect/AccessibleObject.java +++ b/libart/src/main/java/java/lang/reflect/AccessibleObject.java @@ -71,15 +71,8 @@ public class AccessibleObject implements AnnotatedElement { * IllegalAccessExceptions}. */ public void setAccessible(boolean flag) { - try { - if (equals(Class.class.getDeclaredConstructor())) { - throw new SecurityException("Can't make class constructor accessible"); - } - } catch (NoSuchMethodException e) { - throw new AssertionError("Couldn't find class constructor"); - } this.flag = flag; - } + } /** * Attempts to set the accessible flag for all objects in {@code objects}. diff --git a/libart/src/main/java/java/lang/reflect/ArtField.java b/libart/src/main/java/java/lang/reflect/ArtField.java deleted file mode 100644 index 6fdcdb2..0000000 --- a/libart/src/main/java/java/lang/reflect/ArtField.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package java.lang.reflect; - -import com.android.dex.Dex; - -/** - * @hide - */ -public final class ArtField { - - private Class<?> declaringClass; - /** Field access flags (modifiers) */ - private int accessFlags; - /** Index into DexFile's field ids */ - private int fieldDexIndex; - /** Offset of field in object or class */ - private int offset; - - /** - * Only created by art directly. - */ - private ArtField() {} - - public int getAccessFlags() { - return accessFlags; - } - - int getDexFieldIndex() { - return fieldDexIndex; - } - - int getOffset() { - return offset; - } - - public String getName() { - if (fieldDexIndex == -1) { - // Proxy classes have 1 synthesized static field with no valid dex index - if (!declaringClass.isProxy()) { - throw new AssertionError(); - } - return "throws"; - } - Dex dex = declaringClass.getDex(); - int nameIndex = dex.nameIndexFromFieldIndex(fieldDexIndex); - return declaringClass.getDexCacheString(dex, nameIndex); - } - - Class<?> getDeclaringClass() { - return declaringClass; - } - - Class<?> getType() { - if (fieldDexIndex == -1) { - // The type of the synthesized field in a Proxy class is Class[][] - if (!declaringClass.isProxy()) { - throw new AssertionError(); - } - return Class[][].class; - } - Dex dex = declaringClass.getDex(); - int typeIndex = dex.typeIndexFromFieldIndex(fieldDexIndex); - return declaringClass.getDexCacheType(dex, typeIndex); - } -} diff --git a/libart/src/main/java/java/lang/reflect/ArtMethod.java b/libart/src/main/java/java/lang/reflect/ArtMethod.java index 95e03c6..84e6b48 100644 --- a/libart/src/main/java/java/lang/reflect/ArtMethod.java +++ b/libart/src/main/java/java/lang/reflect/ArtMethod.java @@ -75,138 +75,4 @@ public final class ArtMethod { /** Only created by ART directly. */ private ArtMethod() {} - - Class getDeclaringClass() { - return declaringClass; - } - - public int getAccessFlags() { - return accessFlags; - } - - int getDexMethodIndex() { - return dexMethodIndex; - } - - public static String getMethodName(ArtMethod artMethod) { - artMethod = artMethod.findOverriddenMethodIfProxy(); - Dex dex = artMethod.getDeclaringClass().getDex(); - int nameIndex = dex.nameIndexFromMethodIndex(artMethod.getDexMethodIndex()); - // Note, in the case of a Proxy the dex cache strings are equal. - return artMethod.getDexCacheString(dex, nameIndex); - } - - /** - * Returns true if the given parameters match those of the method in the given order. - * - * @hide - */ - public static boolean equalConstructorParameters(ArtMethod artMethod, Class<?>[] params) { - Dex dex = artMethod.getDeclaringClass().getDex(); - short[] types = dex.parameterTypeIndicesFromMethodIndex(artMethod.getDexMethodIndex()); - if (types.length != params.length) { - return false; - } - for (int i = 0; i < types.length; i++) { - if (artMethod.getDexCacheType(dex, types[i]) != params[i]) { - return false; - } - } - return true; - } - - /** - * Returns true if the given parameters match those of this method in the given order. - * - * @hide - */ - public static boolean equalMethodParameters(ArtMethod artMethod, Class<?>[] params) { - return equalConstructorParameters(artMethod.findOverriddenMethodIfProxy(), params); - } - - Class<?>[] getParameterTypes() { - Dex dex = getDeclaringClass().getDex(); - short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex); - if (types.length == 0) { - return EmptyArray.CLASS; - } - Class<?>[] parametersArray = new Class[types.length]; - for (int i = 0; i < types.length; i++) { - // Note, in the case of a Proxy the dex cache types are equal. - parametersArray[i] = getDexCacheType(dex, types[i]); - } - return parametersArray; - } - - Class<?> getReturnType() { - Dex dex = declaringClass.getDex(); - int returnTypeIndex = dex.returnTypeIndexFromMethodIndex(dexMethodIndex); - // Note, in the case of a Proxy the dex cache types are equal. - return getDexCacheType(dex, returnTypeIndex); - } - - /** - * Performs a comparison of the parameters to this method with the given parameters. - * - * @hide - */ - int compareParameters(Class<?>[] params) { - Dex dex = getDeclaringClass().getDex(); - short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex); - int length = Math.min(types.length, params.length); - for (int i = 0; i < length; i++) { - Class<?> aType = getDexCacheType(dex, types[i]); - Class<?> bType = params[i]; - if (aType != bType) { - int comparison = aType.getName().compareTo(bType.getName()); - if (comparison != 0) { - return comparison; - } - } - } - return types.length - params.length; - } - - Annotation[][] getParameterAnnotations() { - return AnnotationAccess.getParameterAnnotations(declaringClass, dexMethodIndex); - } - - /** - * Returns a string from the dex cache, computing the string from the dex file if necessary. - * Note this method replicates {@link java.lang.Class#getDexCacheString(Dex, int)}, but in - * Method we can avoid one indirection. - */ - private String getDexCacheString(Dex dex, int dexStringIndex) { - return declaringClass.getDexCacheString(dex, dexStringIndex); - } - - /** - * Returns a resolved type from the dex cache, computing the string from the dex file if - * necessary. Note this method delegates to {@link java.lang.Class#getDexCacheType(Dex, int)}, - * but in Method we can avoid one indirection. - */ - private Class<?> getDexCacheType(Dex dex, int dexTypeIndex) { - Class<?> resolvedType = dexCacheResolvedTypes[dexTypeIndex]; - if (resolvedType == null) { - resolvedType = declaringClass.getDexCacheType(dex, dexTypeIndex); - } - return resolvedType; - } - - /** - * Returns the {@code ArtMethod} that this method overrides for - * proxy methods, otherwise returns this method. Used to determine - * the interface method overridden by a proxy method (as the proxy - * method doesn't directly support operations such as {@link - * Method#getName}). - */ - ArtMethod findOverriddenMethodIfProxy() { - if (declaringClass.isProxy()) { - // Proxy method's declaring class' dex cache refers to that of Proxy. The local cache in - // Method refers to the original interface's dex cache and is ensured to be resolved by - // proxy generation. - return dexCacheResolvedMethods[dexMethodIndex]; - } - return this; - } } diff --git a/libart/src/main/java/java/lang/reflect/Constructor.java b/libart/src/main/java/java/lang/reflect/Constructor.java index 2eb12b0..9711ef4 100644 --- a/libart/src/main/java/java/lang/reflect/Constructor.java +++ b/libart/src/main/java/java/lang/reflect/Constructor.java @@ -49,11 +49,7 @@ public final class Constructor<T> extends AbstractMethod implements GenericDecla private static final Comparator<Method> ORDER_BY_SIGNATURE = null; // Unused; must match Method. - /** - * @hide - */ - public Constructor(ArtMethod artMethod) { - super(artMethod); + private Constructor() { } public Annotation[] getAnnotations() { @@ -213,7 +209,8 @@ public final class Constructor<T> extends AbstractMethod implements GenericDecla * @return an array of arrays of {@code Annotation} instances */ public Annotation[][] getParameterAnnotations() { - return artMethod.getParameterAnnotations(); + return AnnotationAccess.getParameterAnnotations( + declaringClassOfOverriddenMethod, dexMethodIndex); } /** @@ -283,13 +280,7 @@ public final class Constructor<T> extends AbstractMethod implements GenericDecla * * @see AccessibleObject */ - public T newInstance(Object... args) throws InstantiationException, - IllegalAccessException, IllegalArgumentException, InvocationTargetException { - return newInstance(args, isAccessible()); - } - - /** @hide */ - public native T newInstance(Object[] args, boolean accessible) throws InstantiationException, + public native T newInstance(Object... args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException; /** @@ -330,4 +321,20 @@ public final class Constructor<T> extends AbstractMethod implements GenericDecla return result.toString(); } + + /** + * Attempts to set the accessible flag. Setting this to true prevents {@code + * IllegalAccessExceptions}. + */ + public void setAccessible(boolean flag) { + Class<?> declaringClass = getDeclaringClass(); + if (declaringClass == Class.class) { + throw new SecurityException("Can't make class constructor accessible"); + } else if (declaringClass == Field.class) { + throw new SecurityException("Can't make field constructor accessible"); + } else if (declaringClass == Method.class) { + throw new SecurityException("Can't make method constructor accessible"); + } + super.setAccessible(flag); + } } diff --git a/libart/src/main/java/java/lang/reflect/Field.java b/libart/src/main/java/java/lang/reflect/Field.java index 11e8a6e..37f2ad0 100644 --- a/libart/src/main/java/java/lang/reflect/Field.java +++ b/libart/src/main/java/java/lang/reflect/Field.java @@ -71,16 +71,13 @@ public final class Field extends AccessibleObject implements Member { } }; - private final ArtField artField; + private int accessFlags; + private Class<?> declaringClass; + private int dexFieldIndex; + private int offset; + private Class<?> type; - /** - * @hide - */ - public Field(ArtField artField) { - if (artField == null) { - throw new NullPointerException("artField == null"); - } - this.artField = artField; + private Field() { } /** @@ -91,7 +88,7 @@ public final class Field extends AccessibleObject implements Member { * @see Modifier */ @Override public int getModifiers() { - return artField.getAccessFlags() & 0xffff; // mask out bits not used by Java + return accessFlags & 0xffff; // mask out bits not used by Java } /** @@ -101,7 +98,7 @@ public final class Field extends AccessibleObject implements Member { * false} otherwise */ public boolean isEnumConstant() { - return (artField.getAccessFlags() & Modifier.ENUM) != 0; + return (accessFlags & Modifier.ENUM) != 0; } /** @@ -110,7 +107,7 @@ public final class Field extends AccessibleObject implements Member { * @return {@code true} if this field is synthetic, {@code false} otherwise */ @Override public boolean isSynthetic() { - return (artField.getAccessFlags() & Modifier.SYNTHETIC) != 0; + return (accessFlags & Modifier.SYNTHETIC) != 0; } /** @@ -119,11 +116,20 @@ public final class Field extends AccessibleObject implements Member { * @return the name of this field */ @Override public String getName() { - return artField.getName(); + if (dexFieldIndex == -1) { + // Proxy classes have 1 synthesized static field with no valid dex index. + if (!declaringClass.isProxy()) { + throw new AssertionError(); + } + return "throws"; + } + Dex dex = declaringClass.getDex(); + int nameIndex = dex.nameIndexFromFieldIndex(dexFieldIndex); + return declaringClass.getDexCacheString(dex, nameIndex); } @Override public Class<?> getDeclaringClass() { - return artField.getDeclaringClass(); + return declaringClass; } /** @@ -132,7 +138,7 @@ public final class Field extends AccessibleObject implements Member { * @return the type of this field */ public Class<?> getType() { - return artField.getType(); + return type; } /** @@ -141,7 +147,7 @@ public final class Field extends AccessibleObject implements Member { * @hide */ public int getDexFieldIndex() { - return artField.getDexFieldIndex(); + return dexFieldIndex; } /** @@ -150,7 +156,7 @@ public final class Field extends AccessibleObject implements Member { * @hide */ public int getOffset() { - return artField.getOffset(); + return offset; } /** @@ -170,8 +176,10 @@ public final class Field extends AccessibleObject implements Member { if (!(other instanceof Field)) { return false; } - // exactly one instance of each member in this runtime - return this.artField == ((Field) other).artField; + // Given same declaring class and offset, it must be the same field since no two distinct + // fields can have the same offset. + Field field = (Field)other; + return this.declaringClass == field.declaringClass && this.offset == field.offset; } /** @@ -182,10 +190,12 @@ public final class Field extends AccessibleObject implements Member { */ public String toGenericString() { StringBuilder sb = new StringBuilder(80); + // Limit modifier bits to the ones that toStringGeneric should return for fields. + + String modifiers = Modifier.getDeclarationFieldModifiers(getModifiers()); // append modifiers if any - int modifier = getModifiers(); - if (modifier != 0) { - sb.append(Modifier.toString(modifier)).append(' '); + if (!modifiers.isEmpty()) { + sb.append(modifiers).append(' '); } // append generic type Types.appendGenericType(sb, getGenericType()); @@ -275,11 +285,7 @@ public final class Field extends AccessibleObject implements Member { * @throws IllegalAccessException * if this field is not accessible */ - public Object get(Object object) throws IllegalAccessException, IllegalArgumentException { - return get(object, isAccessible()); - } - - private native Object get(Object object, boolean accessible) + public native Object get(Object object) throws IllegalAccessException, IllegalArgumentException; /** @@ -305,12 +311,7 @@ public final class Field extends AccessibleObject implements Member { * @throws IllegalAccessException * if this field is not accessible */ - public boolean getBoolean(Object object) throws IllegalAccessException, - IllegalArgumentException { - return getBoolean(object, isAccessible()); - } - - private native boolean getBoolean(Object object, boolean accessible) + public native boolean getBoolean(Object object) throws IllegalAccessException, IllegalArgumentException; /** @@ -336,11 +337,7 @@ public final class Field extends AccessibleObject implements Member { * @throws IllegalAccessException * if this field is not accessible */ - public byte getByte(Object object) throws IllegalAccessException, IllegalArgumentException { - return getByte(object, isAccessible()); - } - - private native byte getByte(Object object, boolean accessible) + public native byte getByte(Object object) throws IllegalAccessException, IllegalArgumentException; /** @@ -366,11 +363,7 @@ public final class Field extends AccessibleObject implements Member { * @throws IllegalAccessException * if this field is not accessible */ - public char getChar(Object object) throws IllegalAccessException, IllegalArgumentException { - return getChar(object, isAccessible()); - } - - private native char getChar(Object object, boolean accessible) + public native char getChar(Object object) throws IllegalAccessException, IllegalArgumentException; /** @@ -396,11 +389,7 @@ public final class Field extends AccessibleObject implements Member { * @throws IllegalAccessException * if this field is not accessible */ - public double getDouble(Object object) throws IllegalAccessException, IllegalArgumentException { - return getDouble(object, isAccessible()); - } - - private native double getDouble(Object object, boolean accessible) + public native double getDouble(Object object) throws IllegalAccessException, IllegalArgumentException; /** @@ -426,11 +415,7 @@ public final class Field extends AccessibleObject implements Member { * @throws IllegalAccessException * if this field is not accessible */ - public float getFloat(Object object) throws IllegalAccessException, IllegalArgumentException { - return getFloat(object, isAccessible()); - } - - private native float getFloat(Object object, boolean accessible) + public native float getFloat(Object object) throws IllegalAccessException, IllegalArgumentException; /** @@ -456,11 +441,7 @@ public final class Field extends AccessibleObject implements Member { * @throws IllegalAccessException * if this field is not accessible */ - public int getInt(Object object) throws IllegalAccessException, IllegalArgumentException { - return getInt(object, isAccessible()); - } - - private native int getInt(Object object, boolean accessible) + public native int getInt(Object object) throws IllegalAccessException, IllegalArgumentException; /** @@ -486,11 +467,7 @@ public final class Field extends AccessibleObject implements Member { * @throws IllegalAccessException * if this field is not accessible */ - public long getLong(Object object) throws IllegalAccessException, IllegalArgumentException { - return getLong(object, isAccessible()); - } - - private native long getLong(Object object, boolean accessible) + public native long getLong(Object object) throws IllegalAccessException, IllegalArgumentException; /** @@ -516,11 +493,7 @@ public final class Field extends AccessibleObject implements Member { * @throws IllegalAccessException * if this field is not accessible */ - public short getShort(Object object) throws IllegalAccessException, IllegalArgumentException { - return getShort(object, isAccessible()); - } - - private native short getShort(Object object, boolean accessible) + public native short getShort(Object object) throws IllegalAccessException, IllegalArgumentException; /** @@ -552,12 +525,7 @@ public final class Field extends AccessibleObject implements Member { * @throws IllegalAccessException * if this field is not accessible */ - public void set(Object object, Object value) throws IllegalAccessException, - IllegalArgumentException { - set(object, value, isAccessible()); - } - - private native void set(Object object, Object value, boolean accessible) + public native void set(Object object, Object value) throws IllegalAccessException, IllegalArgumentException; /** @@ -588,12 +556,7 @@ public final class Field extends AccessibleObject implements Member { * @throws IllegalAccessException * if this field is not accessible */ - public void setBoolean(Object object, boolean value) throws IllegalAccessException, - IllegalArgumentException { - setBoolean(object, value, isAccessible()); - } - - private native void setBoolean(Object object, boolean value, boolean accessible) + public native void setBoolean(Object object, boolean value) throws IllegalAccessException, IllegalArgumentException; /** @@ -623,14 +586,8 @@ public final class Field extends AccessibleObject implements Member { * @throws IllegalAccessException * if this field is not accessible */ - public void setByte(Object object, byte value) throws IllegalAccessException, - IllegalArgumentException { - setByte(object, value, isAccessible()); - } - - private native void setByte(Object object, byte value, boolean accessible) + public native void setByte(Object object, byte value) throws IllegalAccessException, IllegalArgumentException; - /** * Sets the value of the field in the specified object to the {@code char} * value. This reproduces the effect of {@code object.fieldName = value} @@ -658,12 +615,7 @@ public final class Field extends AccessibleObject implements Member { * @throws IllegalAccessException * if this field is not accessible */ - public void setChar(Object object, char value) throws IllegalAccessException, - IllegalArgumentException { - setChar(object, value, isAccessible()); - } - - private native void setChar(Object object, char value, boolean accessible) + public native void setChar(Object object, char value) throws IllegalAccessException, IllegalArgumentException; /** @@ -693,12 +645,7 @@ public final class Field extends AccessibleObject implements Member { * @throws IllegalAccessException * if this field is not accessible */ - public void setDouble(Object object, double value) throws IllegalAccessException, - IllegalArgumentException { - setDouble(object, value, isAccessible()); - } - - private native void setDouble(Object object, double value, boolean accessible) + public native void setDouble(Object object, double value) throws IllegalAccessException, IllegalArgumentException; /** @@ -728,12 +675,7 @@ public final class Field extends AccessibleObject implements Member { * @throws IllegalAccessException * if this field is not accessible */ - public void setFloat(Object object, float value) throws IllegalAccessException, - IllegalArgumentException { - setFloat(object, value, isAccessible()); - } - - private native void setFloat(Object object, float value, boolean accessible) + public native void setFloat(Object object, float value) throws IllegalAccessException, IllegalArgumentException; /** @@ -763,12 +705,7 @@ public final class Field extends AccessibleObject implements Member { * @throws IllegalAccessException * if this field is not accessible */ - public void setInt(Object object, int value) throws IllegalAccessException, - IllegalArgumentException { - setInt(object, value, isAccessible()); - } - - private native void setInt(Object object, int value, boolean accessible) + public native void setInt(Object object, int value) throws IllegalAccessException, IllegalArgumentException; /** @@ -798,12 +735,7 @@ public final class Field extends AccessibleObject implements Member { * @throws IllegalAccessException * if this field is not accessible */ - public void setLong(Object object, long value) throws IllegalAccessException, - IllegalArgumentException { - setLong(object, value, isAccessible()); - } - - private native void setLong(Object object, long value, boolean accessible) + public native void setLong(Object object, long value) throws IllegalAccessException, IllegalArgumentException; /** @@ -833,12 +765,7 @@ public final class Field extends AccessibleObject implements Member { * @throws IllegalAccessException * if this field is not accessible */ - public void setShort(Object object, short value) throws IllegalAccessException, - IllegalArgumentException { - setShort(object, value, isAccessible()); - } - - private native void setShort(Object object, short value, boolean accessible) + public native void setShort(Object object, short value) throws IllegalAccessException, IllegalArgumentException; /** @@ -861,7 +788,8 @@ public final class Field extends AccessibleObject implements Member { */ @Override public String toString() { - StringBuilder result = new StringBuilder(Modifier.toString(getModifiers())); + StringBuilder result = new StringBuilder( + Modifier.getDeclarationFieldModifiers(getModifiers())); if (result.length() != 0) { result.append(' '); } diff --git a/libart/src/main/java/java/lang/reflect/Method.java b/libart/src/main/java/java/lang/reflect/Method.java index 058fb96..a07ec6f 100644 --- a/libart/src/main/java/java/lang/reflect/Method.java +++ b/libart/src/main/java/java/lang/reflect/Method.java @@ -57,8 +57,7 @@ public final class Method extends AbstractMethod implements GenericDeclaration, } int comparison = a.getName().compareTo(b.getName()); if (comparison == 0) { - comparison = a.artMethod.findOverriddenMethodIfProxy().compareParameters( - b.getParameterTypes()); + comparison = a.compareParameters(b.getParameterTypes()); if (comparison == 0) { // This is necessary for methods that have covariant return types. Class<?> aReturnType = a.getReturnType(); @@ -77,12 +76,7 @@ public final class Method extends AbstractMethod implements GenericDeclaration, /** * @hide */ - public Method(ArtMethod artMethod) { - super(artMethod); - } - - ArtMethod getArtMethod() { - return artMethod; + private Method() { } public Annotation[] getAnnotations() { @@ -136,7 +130,9 @@ public final class Method extends AbstractMethod implements GenericDeclaration, * @return the name of this method */ @Override public String getName() { - return ArtMethod.getMethodName(artMethod); + Dex dex = declaringClassOfOverriddenMethod.getDex(); + int nameIndex = dex.nameIndexFromMethodIndex(dexMethodIndex); + return declaringClassOfOverriddenMethod.getDexCacheString(dex, nameIndex); } /** @@ -171,7 +167,7 @@ public final class Method extends AbstractMethod implements GenericDeclaration, * @return the parameter types */ @Override public Class<?>[] getParameterTypes() { - return artMethod.findOverriddenMethodIfProxy().getParameterTypes(); + return super.getParameterTypes(); } /** @@ -181,9 +177,13 @@ public final class Method extends AbstractMethod implements GenericDeclaration, * @return the return type */ public Class<?> getReturnType() { - return artMethod.findOverriddenMethodIfProxy().getReturnType(); + Dex dex = declaringClassOfOverriddenMethod.getDex(); + int returnTypeIndex = dex.returnTypeIndexFromMethodIndex(dexMethodIndex); + // Note, in the case of a Proxy the dex cache types are equal. + return declaringClassOfOverriddenMethod.getDexCacheType(dex, returnTypeIndex); } + /** * {@inheritDoc} * @@ -209,8 +209,7 @@ public final class Method extends AbstractMethod implements GenericDeclaration, * @hide needed by Proxy */ boolean equalNameAndParameters(Method m) { - return getName().equals(m.getName()) && - ArtMethod.equalMethodParameters(artMethod,m.getParameterTypes()); + return getName().equals(m.getName()) && equalMethodParameters(m.getParameterTypes()); } /** @@ -310,7 +309,8 @@ public final class Method extends AbstractMethod implements GenericDeclaration, * @return an array of arrays of {@code Annotation} instances */ public Annotation[][] getParameterAnnotations() { - return artMethod.findOverriddenMethodIfProxy().getParameterAnnotations(); + return AnnotationAccess.getParameterAnnotations( + declaringClassOfOverriddenMethod, dexMethodIndex); } /** @@ -367,12 +367,7 @@ public final class Method extends AbstractMethod implements GenericDeclaration, * @throws InvocationTargetException * if an exception was thrown by the invoked method */ - public Object invoke(Object receiver, Object... args) - throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - return invoke(receiver, args, isAccessible()); - } - - private native Object invoke(Object receiver, Object[] args, boolean accessible) + public native Object invoke(Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException; /** @@ -398,7 +393,8 @@ public final class Method extends AbstractMethod implements GenericDeclaration, */ @Override public String toString() { - StringBuilder result = new StringBuilder(Modifier.toString(getModifiers())); + StringBuilder result = new StringBuilder( + Modifier.getDeclarationMethodModifiers(getModifiers())); if (result.length() != 0) { result.append(' '); diff --git a/libart/src/main/java/java/lang/reflect/Proxy.java b/libart/src/main/java/java/lang/reflect/Proxy.java index 31f9cd9..18ad49c 100644..100755 --- a/libart/src/main/java/java/lang/reflect/Proxy.java +++ b/libart/src/main/java/java/lang/reflect/Proxy.java @@ -166,11 +166,7 @@ public class Proxy implements Serializable { Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SUBTYPE); validateReturnTypes(methods); List<Class<?>[]> exceptions = deduplicateAndGetExceptions(methods); - - ArtMethod[] methodsArray = new ArtMethod[methods.size()]; - for (int i = 0; i < methodsArray.length; i++) { - methodsArray[i] = methods.get(i).getArtMethod(); - } + Method[] methodsArray = methods.toArray(new Method[methods.size()]); Class<?>[][] exceptionsArray = exceptions.toArray(new Class<?>[exceptions.size()][]); String baseName = commonPackageName != null && !commonPackageName.isEmpty() @@ -179,7 +175,7 @@ public class Proxy implements Serializable { Class<?> result; synchronized (loader.proxyCache) { - result = loader.proxyCache.get(interfaceSet); + result = loader.proxyCache.get(interfaceList); if (result == null) { String name = baseName + nextClassNameIndex++; result = generateProxy(name, interfaces, loader, methodsArray, exceptionsArray); @@ -383,7 +379,7 @@ public class Proxy implements Serializable { } private static native Class<?> generateProxy(String name, Class<?>[] interfaces, - ClassLoader loader, ArtMethod[] methods, + ClassLoader loader, Method[] methods, Class<?>[][] exceptions); /* @@ -392,8 +388,8 @@ public class Proxy implements Serializable { */ private static native void constructorPrototype(InvocationHandler h); - static Object invoke(Proxy proxy, ArtMethod method, Object[] args) throws Throwable { + private static Object invoke(Proxy proxy, Method method, Object[] args) throws Throwable { InvocationHandler h = proxy.h; - return h.invoke(proxy, new Method(method), args); + return h.invoke(proxy, method, args); } } diff --git a/libart/src/main/java/sun/misc/Unsafe.java b/libart/src/main/java/sun/misc/Unsafe.java index 6f5f5ee..1f938de 100644 --- a/libart/src/main/java/sun/misc/Unsafe.java +++ b/libart/src/main/java/sun/misc/Unsafe.java @@ -294,9 +294,9 @@ public final class Unsafe { */ public void park(boolean absolute, long time) { if (absolute) { - Thread.currentThread().parkUntil(time); + Thread.currentThread().parkUntil$(time); } else { - Thread.currentThread().parkFor(time); + Thread.currentThread().parkFor$(time); } } @@ -310,7 +310,7 @@ public final class Unsafe { */ public void unpark(Object obj) { if (obj instanceof Thread) { - ((Thread) obj).unpark(); + ((Thread) obj).unpark$(); } else { throw new IllegalArgumentException("valid for Threads only"); } |