diff options
24 files changed, 34 insertions, 11128 deletions
@@ -50,26 +50,4 @@ $(info * libcore tests are skipped because environment variable LIBCORE_SKIP_TES $(info ********************************************************************************) endif - -# -# "m dalvik-host" for quick minimal host build -# - -.PHONY: dalvik-host -dalvik-host: \ - dalvik \ - $(HOST_OUT)/bin/dalvikvm \ - $(HOST_OUT)/bin/dexopt \ - $(HOST_OUT)/lib/libjavacore.so \ - $(HOST_OUT)/lib/libjavacrypto.so \ - $(HOST_OUT)/lib/libjavacoretests.so \ - cacerts-host \ - core-hostdex \ - conscrypt-hostdex \ - okhttp-hostdex \ - bouncycastle-hostdex \ - apache-xml-hostdex \ - apache-harmony-tests-hostdex \ - $(call intermediates-dir-for,JAVA_LIBRARIES,core-tests,,COMMON)/classes.jar - include $(subdir_makefiles) @@ -17,8 +17,8 @@ libcore_to_document := \ dalvik/src/main/java/dalvik/annotation \ dalvik/src/main/java/dalvik/bytecode \ json/src/main/java \ - libdvm/src/main/java/dalvik \ - libdvm/src/main/java/java \ + libart/src/main/java/dalvik \ + libart/src/main/java/java \ luni/src/main/java/android \ luni/src/main/java/java \ luni/src/main/java/javax \ diff --git a/JavaLibrary.mk b/JavaLibrary.mk index 8935b9a..c857390 100644 --- a/JavaLibrary.mk +++ b/JavaLibrary.mk @@ -62,7 +62,6 @@ ifneq ($(EMMA_INSTRUMENT_STATIC),true) endif endif -libdvm_core_src_files += $(common_core_src_files) $(call all-main-java-files-under,libdvm) libart_core_src_files += $(common_core_src_files) $(call all-main-java-files-under,libart) local_javac_flags=-encoding UTF-8 @@ -76,18 +75,6 @@ local_javac_flags+=-Xmaxwarns 9999999 # Definitions to make the core library. include $(CLEAR_VARS) -LOCAL_SRC_FILES := $(libdvm_core_src_files) -LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs) -LOCAL_NO_STANDARD_LIBRARIES := true -LOCAL_JAVACFLAGS := $(local_javac_flags) -LOCAL_DX_FLAGS := --core-library -LOCAL_MODULE_TAGS := optional -LOCAL_MODULE := core -LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk -LOCAL_REQUIRED_MODULES := tzdata -include $(BUILD_JAVA_LIBRARY) - -include $(CLEAR_VARS) LOCAL_SRC_FILES := $(libart_core_src_files) LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs) LOCAL_NO_STANDARD_LIBRARIES := true @@ -108,7 +95,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(test_src_files) LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs) LOCAL_NO_STANDARD_LIBRARIES := true -LOCAL_JAVA_LIBRARIES := bouncycastle core core-junit okhttp +LOCAL_JAVA_LIBRARIES := core-libart okhttp core-junit bouncycastle LOCAL_STATIC_JAVA_LIBRARIES := core-tests-support sqlite-jdbc mockwebserver nist-pkix-tests LOCAL_JAVACFLAGS := $(local_javac_flags) LOCAL_MODULE := core-tests @@ -122,7 +109,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-test-java-files-under,support) LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs) LOCAL_NO_STANDARD_LIBRARIES := true -LOCAL_JAVA_LIBRARIES := bouncycastle core core-junit +LOCAL_JAVA_LIBRARIES := core-libart core-junit bouncycastle LOCAL_JAVACFLAGS := $(local_javac_flags) LOCAL_MODULE := core-tests-support LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk @@ -135,7 +122,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-test-java-files-under, jsr166-tests) LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs) LOCAL_NO_STANDARD_LIBRARIES := true -LOCAL_JAVA_LIBRARIES := core core-junit +LOCAL_JAVA_LIBRARIES := core-libart core-junit LOCAL_JAVACFLAGS := $(local_javac_flags) LOCAL_MODULE := jsr166-tests LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk @@ -169,18 +156,6 @@ include $(BUILD_HOST_JAVA_LIBRARY) # Definitions to make the core library. include $(CLEAR_VARS) -LOCAL_SRC_FILES := $(libdvm_core_src_files) -LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs) -LOCAL_NO_STANDARD_LIBRARIES := true -LOCAL_JAVACFLAGS := $(local_javac_flags) -LOCAL_DX_FLAGS := --core-library -LOCAL_MODULE_TAGS := optional -LOCAL_MODULE := core-hostdex -LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk -LOCAL_REQUIRED_MODULES := tzdata-host -include $(BUILD_HOST_DALVIK_JAVA_LIBRARY) - -include $(CLEAR_VARS) LOCAL_SRC_FILES := $(libart_core_src_files) LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs) LOCAL_NO_STANDARD_LIBRARIES := true @@ -200,7 +175,8 @@ ifeq ($(LIBCORE_SKIP_TESTS),) include $(CLEAR_VARS) LOCAL_SRC_FILES := $(test_src_files) LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs) - LOCAL_JAVA_LIBRARIES := bouncycastle-hostdex core-junit-hostdex core-tests-support-hostdex okhttp-hostdex + LOCAL_NO_STANDARD_LIBRARIES := true + LOCAL_JAVA_LIBRARIES := core-libart-hostdex okhttp-hostdex bouncycastle-hostdex core-junit-hostdex core-tests-support-hostdex LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc-host mockwebserver-host nist-pkix-tests-host LOCAL_JAVACFLAGS := $(local_javac_flags) LOCAL_MODULE_TAGS := optional @@ -214,7 +190,8 @@ ifeq ($(LIBCORE_SKIP_TESTS),) include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-test-java-files-under,support) LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs) - LOCAL_JAVA_LIBRARIES := bouncycastle-hostdex core-junit-hostdex + LOCAL_NO_STANDARD_LIBRARIES := true + LOCAL_JAVA_LIBRARIES := core-libart-hostdex core-junit-hostdex bouncycastle-hostdex LOCAL_JAVACFLAGS := $(local_javac_flags) LOCAL_MODULE_TAGS := optional LOCAL_MODULE := core-tests-support-hostdex diff --git a/benchmarks/Android.mk b/benchmarks/Android.mk index b91894f..c0a38a0 100644 --- a/benchmarks/Android.mk +++ b/benchmarks/Android.mk @@ -1,34 +1,39 @@ +# -*- mode: makefile -*- +# Copyright (C) 2013 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. + LOCAL_PATH:= $(call my-dir) -################################################## -include $(CLEAR_VARS) ifeq ($(LIBCORE_SKIP_TESTS),) -# Only compile source java files in this apk. -LOCAL_SRC_FILES := $(call all-java-files-under, src) +################################################## +include $(CLEAR_VARS) LOCAL_MODULE := benchmarks - -LOCAL_STATIC_JAVA_LIBRARIES := \ - caliper-prebuilt \ - core-tests - -LOCAL_JAVA_LIBRARIES := \ - bouncycastle \ - conscrypt \ - core - +LOCAL_SRC_FILES := $(call all-java-files-under, src) +LOCAL_STATIC_JAVA_LIBRARIES := caliper-prebuilt core-tests +LOCAL_NO_STANDARD_LIBRARIES := true +LOCAL_JAVA_LIBRARIES := core-libart conscrypt core-junit bouncycastle framework LOCAL_MODULE_TAGS := tests - LOCAL_MODULE_PATH := $(PRODUCT_OUT)/data/caliperperf - +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk include $(BUILD_JAVA_LIBRARY) ################################################## # Prebuilt Java libraries include $(CLEAR_VARS) - -LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \ - caliper-prebuilt:libs/caliper.jar - +LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := caliper-prebuilt:libs/caliper.jar +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk include $(BUILD_MULTI_PREBUILT) + endif diff --git a/libdvm/src/main/java/dalvik/system/VMRuntime.java b/libdvm/src/main/java/dalvik/system/VMRuntime.java deleted file mode 100644 index 1d58d8d..0000000 --- a/libdvm/src/main/java/dalvik/system/VMRuntime.java +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Copyright (C) 2007 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; - -import java.util.HashMap; -import java.util.Map; - -/** - * Provides an interface to VM-global, Dalvik-specific features. - * An application cannot create its own Runtime instance, and must obtain - * one from the getRuntime method. - * - * @hide - */ -public final class VMRuntime { - - /** - * Holds the VMRuntime singleton. - */ - private static final VMRuntime THE_ONE = new VMRuntime(); - - private static final Map<String, String> ABI_TO_INSTRUCTION_SET_MAP - = new HashMap<String, String>(); - static { - ABI_TO_INSTRUCTION_SET_MAP.put("armeabi", "arm"); - ABI_TO_INSTRUCTION_SET_MAP.put("armeabi-v7a", "arm"); - ABI_TO_INSTRUCTION_SET_MAP.put("mips", "mips"); - ABI_TO_INSTRUCTION_SET_MAP.put("x86", "x86"); - } - - private int targetSdkVersion; - - /** - * Prevents this class from being instantiated. - */ - private VMRuntime() { - } - - /** - * Returns the object that represents the VM instance's Dalvik-specific - * runtime environment. - * - * @return the runtime object - */ - public static VMRuntime getRuntime() { - return THE_ONE; - } - - /** - * Returns a copy of the VM's command-line property settings. - * These are in the form "name=value" rather than "-Dname=value". - */ - public native String[] properties(); - - /** - * Returns the VM's boot class path. - */ - public native String bootClassPath(); - - /** - * Returns the VM's class path. - */ - public native String classPath(); - - /** - * Returns the VM's version. - */ - public native String vmVersion(); - - /** - * Returns the name of the shared library providing the VM implementation. - */ - public native String vmLibrary(); - - /** - * Returns the VM's instruction set. - */ - public String vmInstructionSet() { - return ""; - } - - /** - * Returns whether the VM is running in 64-bit mode. - */ - public boolean is64Bit() { - return false; - } - - /** - * Returns whether the VM is running with JNI checking enabled. - */ - public native boolean isCheckJniEnabled(); - - /** - * Gets the current ideal heap utilization, represented as a number - * between zero and one. After a GC happens, the Dalvik heap may - * be resized so that (size of live objects) / (size of heap) is - * equal to this number. - * - * @return the current ideal heap utilization - */ - public native float getTargetHeapUtilization(); - - /** - * Sets the current ideal heap utilization, represented as a number - * between zero and one. After a GC happens, the Dalvik heap may - * be resized so that (size of live objects) / (size of heap) is - * equal to this number. - * - * <p>This is only a hint to the garbage collector and may be ignored. - * - * @param newTarget the new suggested ideal heap utilization. - * This value may be adjusted internally. - * @return the previous ideal heap utilization - * @throws IllegalArgumentException if newTarget is <= 0.0 or >= 1.0 - */ - public float setTargetHeapUtilization(float newTarget) { - if (newTarget <= 0.0f || newTarget >= 1.0f) { - throw new IllegalArgumentException(newTarget + - " out of range (0,1)"); - } - /* Synchronize to make sure that only one thread gets - * a given "old" value if both update at the same time. - * Allows for reliable save-and-restore semantics. - */ - synchronized (this) { - float oldTarget = getTargetHeapUtilization(); - nativeSetTargetHeapUtilization(newTarget); - return oldTarget; - } - } - - /** - * Sets the target SDK version. Should only be called before the - * app starts to run, because it may change the VM's behavior in - * dangerous ways. Use 0 to mean "current" (since callers won't - * necessarily know the actual current SDK version, and the - * allocated version numbers start at 1), and 10000 to mean - * CUR_DEVELOPMENT. - */ - public synchronized void setTargetSdkVersion(int targetSdkVersion) { - this.targetSdkVersion = targetSdkVersion; - setTargetSdkVersionNative(this.targetSdkVersion); - } - - /** - * Gets the target SDK version. See {@link #setTargetSdkVersion} for - * special values. - */ - public synchronized int getTargetSdkVersion() { - return targetSdkVersion; - } - - private native void setTargetSdkVersionNative(int targetSdkVersion); - - /** - * This method exists for binary compatibility. It was part of a - * heap sizing API which was removed in Android 3.0 (Honeycomb). - */ - @Deprecated - public long getMinimumHeapSize() { - return 0; - } - - /** - * This method exists for binary compatibility. It was part of a - * heap sizing API which was removed in Android 3.0 (Honeycomb). - */ - @Deprecated - public long setMinimumHeapSize(long size) { - return 0; - } - - /** - * This method exists for binary compatibility. It used to - * perform a garbage collection that cleared SoftReferences. - */ - @Deprecated - public void gcSoftReferences() {} - - /** - * This method exists for binary compatibility. It is equivalent - * to {@link System#runFinalization}. - */ - @Deprecated - public void runFinalizationSync() { - System.runFinalization(); - } - - /** - * Implements setTargetHeapUtilization(). - * - * @param newTarget the new suggested ideal heap utilization. - * This value may be adjusted internally. - */ - private native void nativeSetTargetHeapUtilization(float newTarget); - - /** - * This method exists for binary compatibility. It was part of - * the external allocation API which was removed in Android 3.0 (Honeycomb). - */ - @Deprecated - public boolean trackExternalAllocation(long size) { - return true; - } - - /** - * This method exists for binary compatibility. It was part of - * the external allocation API which was removed in Android 3.0 (Honeycomb). - */ - @Deprecated - public void trackExternalFree(long size) {} - - /** - * This method exists for binary compatibility. It was part of - * the external allocation API which was removed in Android 3.0 (Honeycomb). - */ - @Deprecated - public long getExternalBytesAllocated() { - return 0; - } - - /** - * Tells the VM to enable the JIT compiler. If the VM does not have a JIT - * implementation, calling this method should have no effect. - */ - public native void startJitCompilation(); - - /** - * Tells the VM to disable the JIT compiler. If the VM does not have a JIT - * implementation, calling this method should have no effect. - */ - public native void disableJitCompilation(); - - /** - * Returns an array allocated in an area of the Java heap where it will never be moved. - * This is used to implement native allocations on the Java heap, such as DirectByteBuffers - * and Bitmaps. - */ - public native Object newNonMovableArray(Class<?> componentType, int length); - - /** - * Returns an array of at least minLength, but potentially larger. The increased size comes from - * avoiding any padding after the array. The amount of padding varies depending on the - * componentType and the memory allocator implementation. - */ - public Object newUnpaddedArray(Class<?> componentType, int minLength) { - // Dalvik has 32bit pointers, the array header is 16bytes plus 4bytes for dlmalloc, - // allocations are 8byte aligned so having 4bytes of array data avoids padding. - if (!componentType.isPrimitive()) { - int size = ((minLength & 1) == 0) ? minLength + 1 : minLength; - return java.lang.reflect.Array.newInstance(componentType, size); - } else if (componentType == char.class) { - int bytes = 20 + (2 * minLength); - int alignedUpBytes = (bytes + 7) & -8; - int dataBytes = alignedUpBytes - 20; - int size = dataBytes / 2; - return new char[size]; - } else if (componentType == int.class) { - int size = ((minLength & 1) == 0) ? minLength + 1 : minLength; - return new int[size]; - } else if (componentType == byte.class) { - int bytes = 20 + minLength; - int alignedUpBytes = (bytes + 7) & -8; - int dataBytes = alignedUpBytes - 20; - int size = dataBytes; - return new byte[size]; - } else if (componentType == boolean.class) { - int bytes = 20 + minLength; - int alignedUpBytes = (bytes + 7) & -8; - int dataBytes = alignedUpBytes - 20; - int size = dataBytes; - return new boolean[size]; - } else if (componentType == short.class) { - int bytes = 20 + (2 * minLength); - int alignedUpBytes = (bytes + 7) & -8; - int dataBytes = alignedUpBytes - 20; - int size = dataBytes / 2; - return new short[size]; - } else if (componentType == float.class) { - int size = ((minLength & 1) == 0) ? minLength + 1 : minLength; - return new float[size]; - } else if (componentType == long.class) { - return new long[minLength]; - } else if (componentType == double.class) { - return new double[minLength]; - } else { - assert componentType == void.class; - throw new IllegalArgumentException("Can't allocate an array of void"); - } - } - - /** - * Returns the address of array[0]. This differs from using JNI in that JNI might lie and - * give you the address of a copy of the array when in forcecopy mode. - */ - public native long addressOf(Object array); - - /** - * Removes any growth limits, allowing the application to allocate - * up to the maximum heap size. - */ - public native void clearGrowthLimit(); - - /** - * Returns true if either a Java debugger or native debugger is active. - */ - public native boolean isDebuggerActive(); - - /** - * Registers a native allocation so that the heap knows about it and performs GC as required. - * If the number of native allocated bytes exceeds the native allocation watermark, the - * function requests a concurrent GC. If the native bytes allocated exceeds a second higher - * watermark, it is determined that the application is registering native allocations at an - * unusually high rate and a GC is performed inside of the function to prevent memory usage - * from excessively increasing. - */ - public native void registerNativeAllocation(int bytes); - - /** - * Registers a native free by reducing the number of native bytes accounted for. - */ - public native void registerNativeFree(int bytes); - - /** - * Let the heap know of the new process state. This can change allocation and garbage collection - * behavior regarding trimming and compaction. - */ - public native void updateProcessState(int state); - - /** - * Fill in dex caches with classes, fields, and methods that are - * already loaded. Typically used after Zygote preloading. - */ - public native void preloadDexCaches(); - - /** - * Register application info - */ - public static void registerAppInfo(String appDir, String processName, String pkgname) { - // Nothing to do in dalvik. - } - - /** - * Returns the runtime instruction set corresponding to a given ABI. Multiple - * compatible ABIs might map to the same instruction set. For example - * {@code armeabi-v7a} and {@code armeabi} might map to the instruction set {@code arm}. - * - * This influences the compilation of the applications classes. - */ - public static String getInstructionSet(String abi) { - final String instructionSet = ABI_TO_INSTRUCTION_SET_MAP.get(abi); - if (instructionSet == null) { - throw new IllegalArgumentException("Unsupported ABI: " + abi); - } - - return instructionSet; - } -} diff --git a/libdvm/src/main/java/dalvik/system/VMStack.java b/libdvm/src/main/java/dalvik/system/VMStack.java deleted file mode 100644 index bae1829..0000000 --- a/libdvm/src/main/java/dalvik/system/VMStack.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2007 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; - -/** - * Provides a limited interface to the Dalvik VM stack. This class is mostly - * used for implementing security checks. - * - * @hide - */ -public final class VMStack { - /** - * Returns the defining class loader of the caller's caller. - * - * @return the requested class loader, or {@code null} if this is the - * bootstrap class loader. - */ - native public static ClassLoader getCallingClassLoader(); - - /** - * Returns the class of the caller's caller's caller. - * - * @return the requested class, or {@code null}. - */ - native public static Class<?> getStackClass2(); - - /** - * Creates an array of classes from the methods at the top of the stack. - * We continue until we reach the bottom of the stack or exceed the - * specified maximum depth. - * <p> - * The topmost stack frame (this method) and the one above that (the - * caller) are excluded from the array. Frames with java.lang.reflect - * classes are skipped over. - * <p> - * The classes in the array are the defining classes of the methods. - * <p> - * This is similar to Harmony's VMStack.getClasses, except that this - * implementation doesn't have a concept of "privileged" frames. - * - * @param maxDepth - * maximum number of classes to return, or -1 for all - * @return an array with classes for the most-recent methods on the stack - */ - native public static Class<?>[] getClasses(int maxDepth); - - /** - * Returns the first ClassLoader on the call stack that isn't either of - * the passed-in ClassLoaders. - */ - public static ClassLoader getClosestUserClassLoader(ClassLoader bootstrap, - ClassLoader system) { - Class<?>[] stackClasses = VMStack.getClasses(-1); - for (Class<?> stackClass : stackClasses) { - ClassLoader loader = stackClass.getClassLoader(); - if (loader != null && loader != bootstrap && loader != system) { - return loader; - } - } - return null; - } - - /** - * Retrieves the stack trace from the specified thread. - * - * @param t - * thread of interest - * @return an array of stack trace elements, or null if the thread - * doesn't have a stack trace (e.g. because it exited) - */ - native public static StackTraceElement[] getThreadStackTrace(Thread t); - - /** - * Retrieves a partial stack trace from the specified thread into - * the provided array. - * - * @param t - * thread of interest - * @param stackTraceElements - * preallocated array for use when only the top of stack is - * desired. Unused elements will be filled with null values. - * @return the number of elements filled - */ - native public static int fillStackTraceElements(Thread t, - StackTraceElement[] stackTraceElements); -} diff --git a/libdvm/src/main/java/java/lang/Class.java b/libdvm/src/main/java/java/lang/Class.java deleted file mode 100644 index af6278d..0000000 --- a/libdvm/src/main/java/java/lang/Class.java +++ /dev/null @@ -1,1354 +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) 2006-2007 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; - -import com.android.dex.Dex; -import dalvik.system.VMStack; -import java.io.InputStream; -import java.io.Serializable; -import java.lang.annotation.Annotation; -import java.lang.annotation.Inherited; -import java.lang.reflect.AnnotatedElement; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.GenericDeclaration; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.net.URL; -import java.security.ProtectionDomain; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import org.apache.harmony.kernel.vm.StringUtils; -import libcore.reflect.AnnotationAccess; -import libcore.reflect.GenericSignatureParser; -import libcore.reflect.InternalNames; -import libcore.reflect.Types; -import libcore.util.BasicLruCache; -import libcore.util.CollectionUtils; -import libcore.util.EmptyArray; - -/** - * The in-memory representation of a Java class. This representation serves as - * the starting point for querying class-related information, a process usually - * called "reflection". There are basically three types of {@code Class} - * instances: those representing real classes and interfaces, those representing - * primitive types, and those representing array classes. - * - * <h4>Class instances representing object types (classes or interfaces)</h4> - * <p> - * These represent an ordinary class or interface as found in the class - * hierarchy. The name associated with these {@code Class} instances is simply - * the fully qualified class name of the class or interface that it represents. - * In addition to this human-readable name, each class is also associated by a - * so-called <em>signature</em>, which is the letter "L", followed by the - * class name and a semicolon (";"). The signature is what the runtime system - * uses internally for identifying the class (for example in a DEX file). - * </p> - * <h4>Classes representing primitive types</h4> - * <p> - * These represent the standard Java primitive types and hence share their - * names (for example "int" for the {@code int} primitive type). Although it is - * not possible to create new instances based on these {@code Class} instances, - * they are still useful for providing reflection information, and as the - * component type of array classes. There is one {@code Class} instance for each - * primitive type, and their signatures are: - * </p> - * <ul> - * <li>{@code B} representing the {@code byte} primitive type</li> - * <li>{@code S} representing the {@code short} primitive type</li> - * <li>{@code I} representing the {@code int} primitive type</li> - * <li>{@code J} representing the {@code long} primitive type</li> - * <li>{@code F} representing the {@code float} primitive type</li> - * <li>{@code D} representing the {@code double} primitive type</li> - * <li>{@code C} representing the {@code char} primitive type</li> - * <li>{@code Z} representing the {@code boolean} primitive type</li> - * <li>{@code V} representing void function return values</li> - * </ul> - * <p> - * <h4>Classes representing array classes</h4> - * <p> - * These represent the classes of Java arrays. There is one such {@code Class} - * instance per combination of array leaf component type and arity (number of - * dimensions). In this case, the name associated with the {@code Class} - * consists of one or more left square brackets (one per dimension in the array) - * followed by the signature of the class representing the leaf component type, - * which can be either an object type or a primitive type. The signature of a - * {@code Class} representing an array type is the same as its name. Examples - * of array class signatures are: - * </p> - * <ul> - * <li>{@code [I} representing the {@code int[]} type</li> - * <li>{@code [Ljava/lang/String;} representing the {@code String[]} type</li> - * <li>{@code [[[C} representing the {@code char[][][]} type (three dimensions!)</li> - * </ul> - */ -public final class Class<T> implements Serializable, AnnotatedElement, GenericDeclaration, Type { - - private static final long serialVersionUID = 3206093459760846163L; - - /** - * Class def index from dex file. An index of -1 indicates that there is no class definition, - * for example for an array type. - */ - private transient int dexClassDefIndex; - - /** The type index of this class within the dex file that defines it. */ - private transient int dexTypeIndex; - - /** - * Have we computed the type and class def indices? Volatile to avoid double check locking bugs. - */ - private transient volatile boolean dexIndicesInitialized; - - /** - * Lazily computed name of this class; always prefer calling getName(). - */ - private transient String name; - - private Class() { - // Prevent this class to be instantiated, instance - // should be created by JVM only - } - - /** - * Returns the dex file from which this class was loaded. - * @hide - */ - public native Dex getDex(); - - /** Lazily compute indices in to Dex */ - private synchronized void computeDexIndices() { - if (!dexIndicesInitialized) { - Dex dex = getDex(); - dexTypeIndex = dex.findTypeIndex(InternalNames.getInternalName(this)); - if (dexTypeIndex < 0) { - dexTypeIndex = -1; - dexClassDefIndex = -1; - } else { - dexClassDefIndex = dex.findClassDefIndexFromTypeIndex(dexTypeIndex); - } - dexIndicesInitialized = true; - } - } - - /** - * The class def of this class in its own Dex, or -1 if there is no class def. - * - * @hide - */ - public int getDexClassDefIndex() { - if (!dexIndicesInitialized) { - computeDexIndices(); - } - return dexClassDefIndex; - } - - /** - * The type index of this class in its own Dex, or -1 if it is unknown. If a class is referenced - * by multiple Dex files, it will have a different type index in each. Dex files support 65534 - * type indices, with 65535 representing no index. - * - * @hide - */ - public int getDexTypeIndex() { - if (!dexIndicesInitialized) { - computeDexIndices(); - } - return dexTypeIndex; - } - - /** - * Returns a {@code Class} object which represents the class with the - * given name. The name should be the name of a non-primitive class, as described in - * the {@link Class class definition}. - * Primitive types can not be found using this method; use {@code int.class} or {@code Integer.TYPE} instead. - * - * <p>If the class has not yet been loaded, it is loaded and initialized - * first. This is done through either the class loader of the calling class - * or one of its parent class loaders. It is possible that a static initializer is run as - * a result of this call. - * - * @throws ClassNotFoundException - * if the requested class can not be found. - * @throws LinkageError - * if an error occurs during linkage - * @throws ExceptionInInitializerError - * if an exception occurs during static initialization of a - * class. - */ - public static Class<?> forName(String className) throws ClassNotFoundException { - return forName(className, true, VMStack.getCallingClassLoader()); - } - - /** - * Returns a {@code Class} object which represents the class with the - * given name. The name should be the name of a non-primitive class, as described in - * the {@link Class class definition}. - * Primitive types can not be found using this method; use {@code int.class} or {@code Integer.TYPE} instead. - * - * <p>If the class has not yet been loaded, it is loaded first, using the given class loader. - * If the class has not yet been initialized and {@code shouldInitialize} is true, - * the class will be initialized. - * - * @throws ClassNotFoundException - * if the requested class can not be found. - * @throws LinkageError - * if an error occurs during linkage - * @throws ExceptionInInitializerError - * if an exception occurs during static initialization of a - * class. - */ - public static Class<?> forName(String className, boolean shouldInitialize, - ClassLoader classLoader) throws ClassNotFoundException { - - if (classLoader == null) { - classLoader = ClassLoader.getSystemClassLoader(); - } - // Catch an Exception thrown by the underlying native code. It wraps - // up everything inside a ClassNotFoundException, even if e.g. an - // Error occurred during initialization. This as a workaround for - // an ExceptionInInitializerError that's also wrapped. It is actually - // expected to be thrown. Maybe the same goes for other errors. - // Not wrapping up all the errors will break android though. - Class<?> result; - try { - result = classForName(className, shouldInitialize, - classLoader); - } catch (ClassNotFoundException e) { - Throwable cause = e.getCause(); - if (cause instanceof ExceptionInInitializerError) { - throw (ExceptionInInitializerError) cause; - } - throw e; - } - return result; - } - - private static native Class<?> classForName(String className, boolean shouldInitialize, - ClassLoader classLoader) throws ClassNotFoundException; - - /** - * Returns an array containing {@code Class} objects for all public classes - * and interfaces that are members of this class. This includes public - * members inherited from super classes and interfaces. If there are no such - * class members or if this object represents a primitive type then an array - * of length 0 is returned. - */ - public Class<?>[] getClasses() { - Class<?>[] result = getDeclaredClasses(this, true); - // Traverse all superclasses. - for (Class<?> c = this.getSuperclass(); c != null; c = c.getSuperclass()) { - Class<?>[] temp = getDeclaredClasses(c, true); - if (temp.length != 0) { - result = arraycopy(new Class[result.length + temp.length], result, temp); - } - } - return result; - } - - @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) { - if (annotationType == null) { - throw new NullPointerException("annotationType == null"); - } - - A annotation = getDeclaredAnnotation(annotationType); - if (annotation != null) { - return annotation; - } - - if (annotationType.isAnnotationPresent(Inherited.class)) { - for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) { - annotation = sup.getDeclaredAnnotation(annotationType); - if (annotation != null) { - return annotation; - } - } - } - - return null; - } - - /** - * Returns an array containing all the annotations of this class. If there are no annotations - * then an empty array is returned. - * - * @see #getDeclaredAnnotations() - */ - public Annotation[] getAnnotations() { - /* - * We need to get the annotations declared on this class, plus the - * annotations from superclasses that have the "@Inherited" annotation - * set. We create a temporary map to use while we accumulate the - * annotations and convert it to an array at the end. - * - * It's possible to have duplicates when annotations are inherited. - * We use a Map to filter those out. - * - * HashMap might be overkill here. - */ - HashMap<Class, Annotation> map = new HashMap<Class, Annotation>(); - Annotation[] declaredAnnotations = getDeclaredAnnotations(); - - for (int i = declaredAnnotations.length-1; i >= 0; --i) { - map.put(declaredAnnotations[i].annotationType(), declaredAnnotations[i]); - } - for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) { - declaredAnnotations = sup.getDeclaredAnnotations(); - for (int i = declaredAnnotations.length-1; i >= 0; --i) { - Class<?> clazz = declaredAnnotations[i].annotationType(); - if (!map.containsKey(clazz) && clazz.isAnnotationPresent(Inherited.class)) { - map.put(clazz, declaredAnnotations[i]); - } - } - } - - /* convert annotation values from HashMap to array */ - Collection<Annotation> coll = map.values(); - return coll.toArray(new Annotation[coll.size()]); - } - - /** - * Returns the canonical name of this class. If this class does not have a - * canonical name as defined in the Java Language Specification, then the - * method returns {@code null}. - */ - public String getCanonicalName() { - if (isLocalClass() || isAnonymousClass()) - return null; - - if (isArray()) { - /* - * The canonical name of an array type depends on the (existence of) - * the component type's canonical name. - */ - String name = getComponentType().getCanonicalName(); - if (name != null) { - return name + "[]"; - } - } else if (isMemberClass()) { - /* - * The canonical name of an inner class depends on the (existence - * of) the declaring class' canonical name. - */ - String name = getDeclaringClass().getCanonicalName(); - if (name != null) { - return name + "." + getSimpleName(); - } - } else { - /* - * The canonical name of a top-level class or primitive type is - * equal to the fully qualified name. - */ - return getName(); - } - - /* - * Other classes don't have a canonical name. - */ - return null; - } - - /** - * Returns the class loader which was used to load the class represented by - * this {@code Class}. Implementations are free to return {@code null} for - * classes that were loaded by the bootstrap class loader. The Android - * reference implementation, though, always returns a reference to an actual - * class loader. - */ - public ClassLoader getClassLoader() { - if (this.isPrimitive()) { - 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 = getClassLoader(this); - return loader == null ? BootClassLoader.getInstance() : loader; - } - - /* - * Returns the defining class loader for the given class. - */ - private static native ClassLoader getClassLoader(Class<?> c); - - /** - * Returns a {@code Class} object which represents the component type if - * this class represents an array type. Returns {@code null} if this class - * does not represent an array type. The component type of an array type is - * the type of the elements of the array. - */ - public native Class<?> getComponentType(); - - /** - * Returns a {@code Constructor} object which represents the public - * constructor matching the given parameter types. - * {@code (Class[]) null} is equivalent to the empty array. - * - * <p>See {@link #getMethod} for details of the search order. - * Use {@link #getDeclaredConstructor} if you don't want to search superclasses. - * - * @throws NoSuchMethodException - * if the constructor can not be found. - */ - @SuppressWarnings("unchecked") - public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException { - return (Constructor) getConstructorOrMethod("<init>", false, true, parameterTypes); - } - - /** - * Returns a constructor or method with the given name. Use "<init>" to return a constructor. - */ - private Member getConstructorOrMethod(String name, boolean searchSuperTypes, - boolean publicOnly, Class<?>[] parameterTypes) throws NoSuchMethodException { - if (searchSuperTypes && !publicOnly) { - throw new AssertionError(); // can't lookup non-public members recursively - } - if (name == null) { - throw new NullPointerException("name == null"); - } - if (parameterTypes == null) { - parameterTypes = EmptyArray.CLASS; - } - for (Class<?> c : parameterTypes) { - if (c == null) { - throw new NoSuchMethodException("parameter type is null"); - } - } - Member result = searchSuperTypes - ? getPublicConstructorOrMethodRecursive(name, parameterTypes) - : Class.getDeclaredConstructorOrMethod(this, name, parameterTypes); - if (result == null || publicOnly && (result.getModifiers() & Modifier.PUBLIC) == 0) { - throw new NoSuchMethodException(name + " " + Arrays.toString(parameterTypes)); - } - return result; - } - - private Member getPublicConstructorOrMethodRecursive(String name, Class<?>[] parameterTypes) { - // search superclasses - for (Class<?> c = this; c != null; c = c.getSuperclass()) { - Member result = Class.getDeclaredConstructorOrMethod(c, name, parameterTypes); - if (result != null && (result.getModifiers() & Modifier.PUBLIC) != 0) { - return result; - } - } - - // search implemented interfaces - for (Class<?> c = this; c != null; c = c.getSuperclass()) { - for (Class<?> ifc : c.getInterfaces()) { - Member result = ifc.getPublicConstructorOrMethodRecursive(name, parameterTypes); - if (result != null && (result.getModifiers() & Modifier.PUBLIC) != 0) { - return result; - } - } - } - - return null; - } - - /** - * Returns an array containing {@code Constructor} objects for all public - * constructors for this {@code Class}. If there - * are no public constructors or if this {@code Class} represents an array - * class, a primitive type or void then an empty array is returned. - * - * @see #getDeclaredConstructors() - */ - public Constructor<?>[] getConstructors() { - return getDeclaredConstructors(this, true); - } - - /** - * Returns the annotations that are directly defined on the class - * represented by this {@code Class}. Annotations that are inherited are not - * included in the result. If there are no annotations at all, an empty - * array is returned. - * - * @see #getAnnotations() - */ - public native Annotation[] getDeclaredAnnotations(); - - /** - * Returns the annotation if it exists. - */ - native private <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass); - - /** - * Returns true if the annotation exists. - */ - native private boolean isDeclaredAnnotationPresent(Class<? extends Annotation> annotationClass); - - /** - * Returns an array containing {@code Class} objects for all classes and - * interfaces that are declared as members of the class which this {@code - * Class} represents. If there are no classes or interfaces declared or if - * this class represents an array class, a primitive type or void, then an - * empty array is returned. - */ - public Class<?>[] getDeclaredClasses() { - return getDeclaredClasses(this, false); - } - - /* - * Returns the list of member classes of the given class. - * If no members exist, an empty array is returned. - */ - private static native Class<?>[] getDeclaredClasses(Class<?> c, boolean publicOnly); - - /** - * Returns a {@code Constructor} object which represents the constructor - * matching the given parameter types that is declared by the class - * represented by this {@code Class}. - * {@code (Class[]) null} is equivalent to the empty array. - * - * <p>Use {@link #getConstructor} if you want to search superclasses. - * - * @throws NoSuchMethodException - * if the requested constructor can not be found. - */ - @SuppressWarnings("unchecked") - public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) - throws NoSuchMethodException { - return (Constructor) getConstructorOrMethod("<init>", false, false, parameterTypes); - } - - /** - * Returns an array containing {@code Constructor} objects for all - * constructors declared in the class represented by this {@code Class}. If - * there are no constructors or if this {@code Class} represents an array - * class, a primitive type, or void then an empty array is returned. - * - * @see #getConstructors() - */ - public Constructor<?>[] getDeclaredConstructors() { - return getDeclaredConstructors(this, false); - } - - /* - * Returns the list of constructors. If no constructors exist, an empty array is returned. - */ - private static native <T> Constructor<T>[] getDeclaredConstructors(Class<T> c, - boolean publicOnly); - - /** - * Returns a {@code Field} object for the field with the given name - * which is declared in the class represented by this {@code Class}. - * - * @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 = getDeclaredField(this, name); - if (result == null) { - throw new NoSuchFieldException(name); - } - return result; - } - - /** - * Returns an array containing {@code Field} objects for all fields declared - * in the class represented by this {@code Class}. If there are no fields or - * if this {@code Class} represents an array class, a primitive type or void - * then an empty array is returned. - * - * @see #getFields() - */ - public Field[] getDeclaredFields() { - return getDeclaredFields(this, false); - } - - /* - * Returns the list of fields without performing any security checks - * first. If no fields exist at all, an empty array is returned. - */ - static native Field[] getDeclaredFields(Class<?> c, boolean publicOnly); - - /** - * Returns the field if it is defined by {@code c}; null otherwise. This - * may return a non-public member. - */ - static native Field getDeclaredField(Class<?> c, String name); - - /** - * Returns a {@code Method} object which represents the method matching the - * given name and parameter types that is declared by the class - * represented by this {@code Class}. - * {@code (Class[]) null} is equivalent to the empty array. - * - * <p>See {@link #getMethod} if you want to search superclasses. - * - * @throws NoSuchMethodException - * if the requested method can not be found. - * @throws NullPointerException - * if {@code name} is {@code null}. - */ - public Method getDeclaredMethod(String name, Class<?>... parameterTypes) - throws NoSuchMethodException { - Member member = getConstructorOrMethod(name, false, false, parameterTypes); - if (member instanceof Constructor) { - throw new NoSuchMethodException(name); - } - return (Method) member; - } - - /** - * Returns an array containing {@code Method} objects for all methods - * declared in the class represented by this {@code Class}. If there are no - * methods or if this {@code Class} represents an array class, a primitive - * type or void then an empty array is returned. - * - * @see #getMethods() - */ - public Method[] getDeclaredMethods() { - return getDeclaredMethods(this, false); - } - - /** - * Returns the list of methods. If no methods exist, an empty array is returned. - */ - static native Method[] getDeclaredMethods(Class<?> c, boolean publicOnly); - - /** - * Returns the constructor or method if it is defined by {@code c}; null - * otherwise. This may return a non-public member. Use "<init>" to get a constructor. - */ - static native Member getDeclaredConstructorOrMethod(Class c, String name, Class[] args); - - /** - * Returns the declaring {@code Class} of this {@code Class}. Returns - * {@code null} if the class is not a member of another class or if this - * {@code Class} represents an array class, a primitive type, or void. - */ - public native Class<?> getDeclaringClass(); - - /** - * Returns the enclosing {@code Class} of this {@code Class}. If there is no - * enclosing class the method returns {@code null}. - */ - public native Class<?> getEnclosingClass(); - - /** - * Returns the enclosing {@code Constructor} of this {@code Class}, if it is an - * anonymous or local/automatic class; otherwise {@code null}. - */ - public native Constructor<?> getEnclosingConstructor(); - - /** - * Returns the enclosing {@code Method} of this {@code Class}, if it is an - * anonymous or local/automatic class; otherwise {@code null}. - */ - public native Method getEnclosingMethod(); - - /** - * Returns the {@code enum} constants associated with this {@code Class}. - * Returns {@code null} if this {@code Class} does not represent an {@code - * enum} type. - */ - @SuppressWarnings("unchecked") // we only cast after confirming that this class is an enum - public T[] getEnumConstants() { - if (!isEnum()) { - return null; - } - return (T[]) Enum.getSharedConstants((Class) this).clone(); - } - - /** - * Returns a {@code Field} object which represents the public field with the - * given name. This method first searches the class C represented by - * this {@code Class}, then the interfaces implemented by C and finally the - * superclasses of C. - * - * @throws NoSuchFieldException - * if the field can not be found. - * @see #getDeclaredField(String) - */ - public Field getField(String name) throws NoSuchFieldException { - if (name == null) { - throw new NullPointerException("name == null"); - } - Field result = getPublicFieldRecursive(name); - if (result == null) { - throw new NoSuchFieldException(name); - } - return result; - } - - private Field getPublicFieldRecursive(String name) { - // search superclasses - for (Class<?> c = this; c != null; c = c.getSuperclass()) { - Field result = Class.getDeclaredField(c, name); - if (result != null && (result.getModifiers() & Modifier.PUBLIC) != 0) { - return result; - } - } - - // search implemented interfaces - for (Class<?> c = this; c != null; c = c.getSuperclass()) { - for (Class<?> ifc : c.getInterfaces()) { - Field result = ifc.getPublicFieldRecursive(name); - if (result != null && (result.getModifiers() & Modifier.PUBLIC) != 0) { - return result; - } - } - } - - return null; - } - - /** - * Returns an array containing {@code Field} objects for all public fields - * for the class C represented by this {@code Class}. Fields may be declared - * in C, the interfaces it implements or in the superclasses of C. The - * elements in the returned array are in no particular order. - * - * <p>If there are no public fields or if this class represents an array class, - * a primitive type or {@code void} then an empty array is returned. - * - * @see #getDeclaredFields() - */ - public Field[] getFields() { - List<Field> fields = new ArrayList<Field>(); - getPublicFieldsRecursive(fields); - - /* - * The result may include duplicates when this class implements an interface - * through multiple paths. Remove those duplicates. - */ - CollectionUtils.removeDuplicates(fields, Field.ORDER_BY_NAME_AND_DECLARING_CLASS); - return fields.toArray(new Field[fields.size()]); - } - - /** - * Populates {@code result} with public fields defined by this class, its - * superclasses, and all implemented interfaces. - */ - private void getPublicFieldsRecursive(List<Field> result) { - // search superclasses - for (Class<?> c = this; c != null; c = c.getSuperclass()) { - for (Field field : Class.getDeclaredFields(c, true)) { - result.add(field); - } - } - - // search implemented interfaces - for (Class<?> c = this; c != null; c = c.getSuperclass()) { - for (Class<?> ifc : c.getInterfaces()) { - ifc.getPublicFieldsRecursive(result); - } - } - } - - /** - * Returns the {@link Type}s of the interfaces that this {@code Class} directly - * implements. If the {@code Class} represents a primitive type or {@code - * void} then an empty array is returned. - */ - public Type[] getGenericInterfaces() { - Type[] result; - synchronized (Caches.genericInterfaces) { - result = Caches.genericInterfaces.get(this); - if (result == null) { - String annotationSignature = AnnotationAccess.getSignature(this); - if (annotationSignature == null) { - result = getInterfaces(); - } else { - GenericSignatureParser parser = new GenericSignatureParser(getClassLoader()); - parser.parseForClass(this, annotationSignature); - result = Types.getTypeArray(parser.interfaceTypes, false); - } - Caches.genericInterfaces.put(this, result); - } - } - return (result.length == 0) ? result : result.clone(); - } - - /** - * Returns the {@code Type} that represents the superclass of this {@code - * class}. - */ - public Type getGenericSuperclass() { - Type genericSuperclass = getSuperclass(); - // This method is specified to return null for all cases where getSuperclass - // returns null, i.e, for primitives, interfaces, void and java.lang.Object. - - if (genericSuperclass == null) { - return null; - } - String annotationSignature = AnnotationAccess.getSignature(this); - if (annotationSignature != null) { - GenericSignatureParser parser = new GenericSignatureParser(getClassLoader()); - parser.parseForClass(this, annotationSignature); - genericSuperclass = parser.superclassType; - } - return Types.getType(genericSuperclass); - } - - /** - * Returns an array of {@code Class} objects that match the interfaces - * in the {@code implements} declaration of the class represented - * by this {@code Class}. The order of the elements in the array is - * identical to the order in the original class declaration. If the class - * does not implement any interfaces, an empty array is returned. - */ - public native Class<?>[] getInterfaces(); - - /** - * Returns a {@code Method} object which represents the public method with - * the given name and parameter types. - * {@code (Class[]) null} is equivalent to the empty array. - * - * <p>This method first searches the class C represented by this {@code Class}, - * then the superclasses of C, - * and finally the interfaces implemented by C and its superclasses. - * - * <p>Use {@link #getDeclaredMethod} if you don't want to search superclasses. - * - * @throws NoSuchMethodException - * if the method can not be found. - */ - public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException { - Member member = getConstructorOrMethod(name, true, true, parameterTypes); - if (member instanceof Constructor) { - throw new NoSuchMethodException(name); - } - return (Method) member; - } - - /** - * Returns an array containing {@code Method} objects for all public methods - * for the class C represented by this {@code Class}. Methods may be - * declared in C, the interfaces it implements or in the superclasses of C. - * The elements in the returned array are in no particular order. - * - * <p>If there are no public methods or if this {@code Class} represents a - * primitive type or {@code void} then an empty array is returned. - * - * @see #getDeclaredMethods() - */ - public Method[] getMethods() { - List<Method> methods = new ArrayList<Method>(); - getPublicMethodsRecursive(methods); - - /* - * Remove methods defined by multiple types, preferring to keep methods - * declared by derived types. - */ - CollectionUtils.removeDuplicates(methods, Method.ORDER_BY_SIGNATURE); - return methods.toArray(new Method[methods.size()]); - } - - /** - * Populates {@code result} with public methods defined by this class, its - * superclasses, and all implemented interfaces, including overridden methods. - */ - private void getPublicMethodsRecursive(List<Method> result) { - // search superclasses - for (Class<?> c = this; c != null; c = c.getSuperclass()) { - for (Method method : Class.getDeclaredMethods(c, true)) { - result.add(method); - } - } - - // search implemented interfaces - for (Class<?> c = this; c != null; c = c.getSuperclass()) { - for (Class<?> ifc : c.getInterfaces()) { - ifc.getPublicMethodsRecursive(result); - } - } - } - - /** - * Returns an integer that represents the modifiers of the class represented - * by this {@code Class}. The returned value is a combination of bits - * defined by constants in the {@link Modifier} class. - */ - public int getModifiers() { - return getModifiers(this, false); - } - - /* - * Returns the modifiers for the given class. - * - * {@code ignoreInnerClassesAttrib} determines whether we look for and use the - * flags from an "inner class" attribute - */ - private static native int getModifiers(Class<?> clazz, boolean ignoreInnerClassesAttrib); - - /** - * Returns the name of the class represented by this {@code Class}. For a - * description of the format which is used, see the class definition of - * {@link Class}. - */ - public String getName() { - String result = name; - return (result == null) ? (name = getNameNative()) : result; - } - - private native String getNameNative(); - - /** - * Returns the simple name of the class represented by this {@code Class} as - * defined in the source code. If there is no name (that is, the class is - * anonymous) then an empty string is returned. If the receiver is an array - * then the name of the underlying type with square braces appended (for - * example {@code "Integer[]"}) is returned. - * - * @return the simple name of the class represented by this {@code Class}. - */ - public String getSimpleName() { - if (isArray()) { - return getComponentType().getSimpleName() + "[]"; - } - - String name = getName(); - - if (isAnonymousClass()) { - return ""; - } - - if (isMemberClass() || isLocalClass()) { - return getInnerClassName(); - } - - int dot = name.lastIndexOf('.'); - if (dot != -1) { - return name.substring(dot + 1); - } - - return name; - } - - /* - * Returns the simple name of a member or local class, or null otherwise. - */ - private native String getInnerClassName(); - - /** - * Returns null. - */ - public ProtectionDomain getProtectionDomain() { - return null; - } - - /** - * Returns the URL of the given resource, or 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 - */ - public URL getResource(String resourceName) { - // Get absolute resource name, but without the leading slash - if (resourceName.startsWith("/")) { - resourceName = resourceName.substring(1); - } else { - String pkg = getName(); - int dot = pkg.lastIndexOf('.'); - if (dot != -1) { - pkg = pkg.substring(0, dot).replace('.', '/'); - } else { - pkg = ""; - } - - resourceName = pkg + "/" + resourceName; - } - - // Delegate to proper class loader - ClassLoader loader = getClassLoader(); - if (loader != null) { - return loader.getResource(resourceName); - } else { - return ClassLoader.getSystemResource(resourceName); - } - } - - /** - * Returns a read-only stream for the contents of the given resource, or 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 - */ - public InputStream getResourceAsStream(String resourceName) { - // Get absolute resource name, but without the leading slash - if (resourceName.startsWith("/")) { - resourceName = resourceName.substring(1); - } else { - String pkg = getName(); - int dot = pkg.lastIndexOf('.'); - if (dot != -1) { - pkg = pkg.substring(0, dot).replace('.', '/'); - } else { - pkg = ""; - } - - resourceName = pkg + "/" + resourceName; - } - - // Delegate to proper class loader - ClassLoader loader = getClassLoader(); - if (loader != null) { - return loader.getResourceAsStream(resourceName); - } else { - return ClassLoader.getSystemResourceAsStream(resourceName); - } - } - - /** - * 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 - * files may have different signers. This does not fit well with the original - * {@code ClassLoader}-based model of {@code getSigners}.) - */ - public Object[] getSigners() { - // See http://code.google.com/p/android/issues/detail?id=1766. - return null; - } - - /** - * Returns the {@code Class} object which represents the superclass of the - * class represented by this {@code Class}. If this {@code Class} represents - * the {@code Object} class, a primitive type, an interface or void then the - * method returns {@code null}. If this {@code Class} represents an array - * class then the {@code Object} class is returned. - */ - public native Class<? super T> getSuperclass(); - - /** - * Returns an array containing {@code TypeVariable} objects for type - * variables declared by the generic class represented by this {@code - * Class}. Returns an empty array if the class is not generic. - */ - @SuppressWarnings("unchecked") - public synchronized TypeVariable<Class<T>>[] getTypeParameters() { - String annotationSignature = AnnotationAccess.getSignature(this); - if (annotationSignature == null) { - return EmptyArray.TYPE_VARIABLE; - } - GenericSignatureParser parser = new GenericSignatureParser(getClassLoader()); - parser.parseForClass(this, annotationSignature); - return parser.formalTypeParameters; - } - - /** - * Tests whether this {@code Class} represents an annotation class. - */ - public boolean isAnnotation() { - final int ACC_ANNOTATION = 0x2000; // not public in reflect.Modifiers - int mod = getModifiers(this, true); - return (mod & ACC_ANNOTATION) != 0; - } - - @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) { - if (annotationType == null) { - throw new NullPointerException("annotationType == null"); - } - - if (isDeclaredAnnotationPresent(annotationType)) { - return true; - } - - if (annotationType.isDeclaredAnnotationPresent(Inherited.class)) { - for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) { - if (sup.isDeclaredAnnotationPresent(annotationType)) { - return true; - } - } - } - - return false; - } - - /** - * Tests whether the class represented by this {@code Class} is - * anonymous. - */ - native public boolean isAnonymousClass(); - - /** - * Tests whether the class represented by this {@code Class} is an array class. - */ - public boolean isArray() { - return getComponentType() != null; - } - - /** - * Tests whether the given class type can be converted to the class - * represented by this {@code Class}. Conversion may be done via an identity - * conversion or a widening reference conversion (if either the receiver or - * the argument represent primitive types, only the identity conversion - * applies). - * - * @throws NullPointerException - * if {@code c} is {@code null}. - */ - public native boolean isAssignableFrom(Class<?> c); - - /** - * Tests whether the class represented by this {@code Class} is an - * {@code enum}. - */ - public boolean isEnum() { - if (getSuperclass() != Enum.class) { - return false; - } - int mod = getModifiers(this, true); - return (mod & 0x4000) != 0; - } - - /** - * Tests whether the given object can be cast to the class - * represented by this {@code Class}. This is the runtime version of the - * {@code instanceof} operator. - * - * @return {@code true} if {@code object} can be cast to the type - * represented by this {@code Class}; {@code false} if {@code - * object} is {@code null} or cannot be cast. - */ - public native boolean isInstance(Object object); - - /** - * Tests whether this {@code Class} represents an interface. - */ - public native boolean isInterface(); - - /** - * Tests whether the class represented by this {@code Class} is defined - * locally. - */ - public boolean isLocalClass() { - boolean enclosed = (getEnclosingMethod() != null || - getEnclosingConstructor() != null); - return enclosed && !isAnonymousClass(); - } - - /** - * Tests whether the class represented by this {@code Class} is a member - * class. - */ - public boolean isMemberClass() { - return getDeclaringClass() != null; - } - - /** - * Tests whether this {@code Class} represents a primitive type. - */ - public native boolean isPrimitive(); - - /** - * Tests whether this {@code Class} represents a synthetic type. - */ - public boolean isSynthetic() { - final int ACC_SYNTHETIC = 0x1000; // not public in reflect.Modifiers - int mod = getModifiers(this, true); - return (mod & ACC_SYNTHETIC) != 0; - } - - /** - * Returns a new instance of the class represented by this {@code Class}, - * created by invoking the default (that is, zero-argument) constructor. If - * there is no such constructor, or if the creation fails (either because of - * a lack of available memory or because an exception is thrown by the - * constructor), an {@code InstantiationException} is thrown. If the default - * constructor exists but is not accessible from the context where this - * method is invoked, an {@code IllegalAccessException} is thrown. - * - * @throws IllegalAccessException - * if the default constructor is not visible. - * @throws InstantiationException - * if the instance can not be created. - */ - public T newInstance() throws InstantiationException, IllegalAccessException { - return newInstanceImpl(); - } - - private native T newInstanceImpl() throws IllegalAccessException, InstantiationException; - - @Override - public String toString() { - if (isPrimitive()) { - return getSimpleName(); - } - return (isInterface() ? "interface " : "class ") + getName(); - } - - /** - * Returns the {@code Package} of which the class represented by this - * {@code Class} is a member. Returns {@code null} if no {@code Package} - * 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. - ClassLoader loader = getClassLoader(); - if (loader != null) { - String name = getName(); - int dot = name.lastIndexOf('.'); - return (dot != -1 ? loader.getPackage(name.substring(0, dot)) : null); - } - return null; - } - - /** - * Returns the assertion status for the class represented by this {@code - * Class}. Assertion is enabled / disabled based on the class loader, - * package or class default at runtime. - */ - public native boolean desiredAssertionStatus(); - - /** - * Casts this {@code Class} to represent a subclass of the given class. - * If successful, this {@code Class} is returned; otherwise a {@code - * ClassCastException} is thrown. - * - * @throws ClassCastException - * if this {@code Class} cannot be cast to the given type. - */ - @SuppressWarnings("unchecked") - public <U> Class<? extends U> asSubclass(Class<U> c) { - if (c.isAssignableFrom(this)) { - return (Class<? extends U>)this; - } - String actualClassName = this.getName(); - String desiredClassName = c.getName(); - throw new ClassCastException(actualClassName + " cannot be cast to " + desiredClassName); - } - - /** - * Casts the given object to the type represented by this {@code Class}. - * If the object is {@code null} then the result is also {@code null}. - * - * @throws ClassCastException - * if the object cannot be cast to the given type. - */ - @SuppressWarnings("unchecked") - public T cast(Object obj) { - if (obj == null) { - return null; - } else if (this.isInstance(obj)) { - return (T)obj; - } - String actualClassName = obj.getClass().getName(); - String desiredClassName = this.getName(); - throw new ClassCastException(actualClassName + " cannot be cast to " + desiredClassName); - } - - /** - * Copies two arrays into one. Assumes that the destination array is large - * enough. - * - * @param result the destination array - * @param head the first source array - * @param tail the second source array - * @return the destination array, that is, result - */ - private static <T extends Object> T[] arraycopy(T[] result, T[] head, T[] tail) { - System.arraycopy(head, 0, result, 0, head.length); - System.arraycopy(tail, 0, result, head.length, tail.length); - return result; - } - - /** - * The annotation directory offset of this class in its own Dex, or 0 if it - * is unknown. - * - * TODO: 0 is a sentinel that means 'no annotations directory'; this should be -1 if unknown - * - * @hide - */ - public int getDexAnnotationDirectoryOffset() { - Dex dex = getDex(); - if (dex == null) { - return 0; - } - int classDefIndex = getDexClassDefIndex(); - if (classDefIndex < 0) { - return 0; - } - return dex.annotationDirectoryOffsetFromClassDefIndex(classDefIndex); - } - - - /** - * Returns a resolved type from the dex cache, computing the type from the dex file if - * necessary. - * TODO: use Dalvik's dex cache. - * @hide - */ - public Class<?> getDexCacheType(Dex dex, int typeIndex) { - String internalName = dex.typeNames().get(typeIndex); - return InternalNames.getClass(getClassLoader(), internalName); - } - - /** - * Returns a string from the dex cache, computing the string from the dex file if necessary. - * - * @hide - */ - public String getDexCacheString(Dex dex, int dexStringIndex) { - return dex.strings().get(dexStringIndex); - } - - - private static class Caches { - /** - * Cache to avoid frequent recalculation of generic interfaces, which is generally uncommon. - * Sized sufficient to allow ConcurrentHashMapTest to run without recalculating its generic - * interfaces (required to avoid time outs). Validated by running reflection heavy code - * such as applications using Guice-like frameworks. - */ - private static final BasicLruCache<Class, Type[]> genericInterfaces - = new BasicLruCache<Class, Type[]>(8); - } -} diff --git a/libdvm/src/main/java/java/lang/ClassLoader.java b/libdvm/src/main/java/java/lang/ClassLoader.java deleted file mode 100644 index c6a8091..0000000 --- a/libdvm/src/main/java/java/lang/ClassLoader.java +++ /dev/null @@ -1,836 +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; - -import dalvik.system.PathClassLoader; -import dalvik.system.VMStack; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.nio.ByteBuffer; -import java.security.ProtectionDomain; -import java.util.Collection; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; - -/** - * Loads classes and resources from a repository. One or more class loaders are - * installed at runtime. These are consulted whenever the runtime system needs a - * specific class that is not yet available in-memory. Typically, class loaders - * are grouped into a tree where child class loaders delegate all requests to - * parent class loaders. Only if the parent class loader cannot satisfy the - * request, the child class loader itself tries to handle it. - * <p> - * {@code ClassLoader} is an abstract class that implements the common - * infrastructure required by all class loaders. Android provides several - * concrete implementations of the class, with - * {@link dalvik.system.PathClassLoader} being the one typically used. Other - * applications may implement subclasses of {@code ClassLoader} to provide - * special ways for loading classes. - * </p> - * @see Class - */ -public abstract class ClassLoader { - - /** - * The 'System' ClassLoader - the one that is responsible for loading - * classes from the classpath. It is not equal to the bootstrap class loader - - * that one handles the built-in classes. - * - * Because of a potential class initialization race between ClassLoader and - * java.lang.System, reproducible when using JDWP with "suspend=y", we defer - * creation of the system class loader until first use. We use a static - * inner class to get synchronization at init time without having to sync on - * every access. - * - * @see #getSystemClassLoader() - */ - static private class SystemClassLoader { - public static ClassLoader loader = ClassLoader.createSystemClassLoader(); - } - - /** - * The parent ClassLoader. - */ - private ClassLoader parent; - - /** - * The packages known to the class loader. - */ - private Map<String, Package> packages = new HashMap<String, Package>(); - - /** - * Create the system class loader. Note this is NOT the bootstrap class - * loader (which is managed by the VM). We use a null value for the parent - * to indicate that the bootstrap loader is our parent. - */ - private static ClassLoader createSystemClassLoader() { - String classPath = System.getProperty("java.class.path", "."); - - // String[] paths = classPath.split(":"); - // URL[] urls = new URL[paths.length]; - // for (int i = 0; i < paths.length; i++) { - // try { - // urls[i] = new URL("file://" + paths[i]); - // } - // catch (Exception ex) { - // ex.printStackTrace(); - // } - // } - // - // return new java.net.URLClassLoader(urls, null); - - // TODO Make this a java.net.URLClassLoader once we have those? - return new PathClassLoader(classPath, BootClassLoader.getInstance()); - } - - /** - * Returns the system class loader. This is the parent for new - * {@code ClassLoader} instances and is typically the class loader used to - * start the application. - */ - public static ClassLoader getSystemClassLoader() { - return SystemClassLoader.loader; - } - - /** - * Finds the URL of the resource with the specified name. The system class - * loader's resource lookup algorithm is used to find the resource. - * - * @return the {@code URL} object for the requested resource or {@code null} - * if the resource can not be found. - * @param resName - * the name of the resource to find. - * @see Class#getResource - */ - public static URL getSystemResource(String resName) { - return SystemClassLoader.loader.getResource(resName); - } - - /** - * Returns an enumeration of URLs for the resource with the specified name. - * The system class loader's resource lookup algorithm is used to find the - * resource. - * - * @return an enumeration of {@code URL} objects containing the requested - * resources. - * @param resName - * the name of the resource to find. - * @throws IOException - * if an I/O error occurs. - */ - public static Enumeration<URL> getSystemResources(String resName) throws IOException { - return SystemClassLoader.loader.getResources(resName); - } - - /** - * Returns a stream for the resource with the specified name. The system - * class loader's resource lookup algorithm is used to find the resource. - * Basically, the contents of the java.class.path are searched in order, - * looking for a path which matches the specified resource. - * - * @return a stream for the resource or {@code null}. - * @param resName - * the name of the resource to find. - * @see Class#getResourceAsStream - */ - public static InputStream getSystemResourceAsStream(String resName) { - return SystemClassLoader.loader.getResourceAsStream(resName); - } - - /** - * Constructs a new instance of this class with the system class loader as - * its parent. - */ - protected ClassLoader() { - this(getSystemClassLoader(), false); - } - - /** - * Constructs a new instance of this class with the specified class loader - * as its parent. - * - * @param parentLoader - * The {@code ClassLoader} to use as the new class loader's - * parent. - */ - protected ClassLoader(ClassLoader parentLoader) { - this(parentLoader, false); - } - - /* - * constructor for the BootClassLoader which needs parent to be null. - */ - ClassLoader(ClassLoader parentLoader, boolean nullAllowed) { - if (parentLoader == null && !nullAllowed) { - throw new NullPointerException("parentLoader == null && !nullAllowed"); - } - parent = parentLoader; - } - - /** - * Constructs a new class from an array of bytes containing a class - * definition in class file format. - * - * @param classRep - * the memory image of a class file. - * @param offset - * the offset into {@code classRep}. - * @param length - * the length of the class file. - * @return the {@code Class} object created from the specified subset of - * data in {@code classRep}. - * @throws ClassFormatError - * if {@code classRep} does not contain a valid class. - * @throws IndexOutOfBoundsException - * if {@code offset < 0}, {@code length < 0} or if - * {@code offset + length} is greater than the length of - * {@code classRep}. - * @deprecated Use {@link #defineClass(String, byte[], int, int)} instead. - */ - @Deprecated - protected final Class<?> defineClass(byte[] classRep, int offset, int length) - throws ClassFormatError { - throw new UnsupportedOperationException("can't load this type of class file"); - } - - /** - * Constructs a new class from an array of bytes containing a class - * definition in class file format. - * - * @param className - * the expected name of the new class, may be {@code null} if not - * known. - * @param classRep - * the memory image of a class file. - * @param offset - * the offset into {@code classRep}. - * @param length - * the length of the class file. - * @return the {@code Class} object created from the specified subset of - * data in {@code classRep}. - * @throws ClassFormatError - * if {@code classRep} does not contain a valid class. - * @throws IndexOutOfBoundsException - * if {@code offset < 0}, {@code length < 0} or if - * {@code offset + length} is greater than the length of - * {@code classRep}. - */ - protected final Class<?> defineClass(String className, byte[] classRep, int offset, int length) - throws ClassFormatError { - throw new UnsupportedOperationException("can't load this type of class file"); - } - - /** - * Constructs a new class from an array of bytes containing a class - * definition in class file format and assigns the specified protection - * domain to the new class. If the provided protection domain is - * {@code null} then a default protection domain is assigned to the class. - * - * @param className - * the expected name of the new class, may be {@code null} if not - * known. - * @param classRep - * the memory image of a class file. - * @param offset - * the offset into {@code classRep}. - * @param length - * the length of the class file. - * @param protectionDomain - * the protection domain to assign to the loaded class, may be - * {@code null}. - * @return the {@code Class} object created from the specified subset of - * data in {@code classRep}. - * @throws ClassFormatError - * if {@code classRep} does not contain a valid class. - * @throws IndexOutOfBoundsException - * if {@code offset < 0}, {@code length < 0} or if - * {@code offset + length} is greater than the length of - * {@code classRep}. - * @throws NoClassDefFoundError - * if {@code className} is not equal to the name of the class - * contained in {@code classRep}. - */ - protected final Class<?> defineClass(String className, byte[] classRep, int offset, int length, - ProtectionDomain protectionDomain) throws java.lang.ClassFormatError { - throw new UnsupportedOperationException("can't load this type of class file"); - } - - /** - * Defines a new class with the specified name, byte code from the byte - * buffer and the optional protection domain. If the provided protection - * domain is {@code null} then a default protection domain is assigned to - * the class. - * - * @param name - * the expected name of the new class, may be {@code null} if not - * known. - * @param b - * the byte buffer containing the byte code of the new class. - * @param protectionDomain - * the protection domain to assign to the loaded class, may be - * {@code null}. - * @return the {@code Class} object created from the data in {@code b}. - * @throws ClassFormatError - * if {@code b} does not contain a valid class. - * @throws NoClassDefFoundError - * if {@code className} is not equal to the name of the class - * contained in {@code b}. - */ - protected final Class<?> defineClass(String name, ByteBuffer b, - ProtectionDomain protectionDomain) throws ClassFormatError { - - byte[] temp = new byte[b.remaining()]; - b.get(temp); - return defineClass(name, temp, 0, temp.length, protectionDomain); - } - - /** - * Overridden by subclasses, throws a {@code ClassNotFoundException} by - * default. This method is called by {@code loadClass} after the parent - * {@code ClassLoader} has failed to find a loaded class of the same name. - * - * @param className - * the name of the class to look for. - * @return the {@code Class} object that is found. - * @throws ClassNotFoundException - * if the class cannot be found. - */ - protected Class<?> findClass(String className) throws ClassNotFoundException { - throw new ClassNotFoundException(className); - } - - /** - * Returns the class with the specified name if it has already been loaded - * by the VM or {@code null} if it has not yet been loaded. - * - * @param className - * the name of the class to look for. - * @return the {@code Class} object or {@code null} if the requested class - * has not been loaded. - */ - protected final Class<?> findLoadedClass(String className) { - ClassLoader loader; - if (this == BootClassLoader.getInstance()) - loader = null; - else - loader = this; - return VMClassLoader.findLoadedClass(loader, className); - } - - /** - * Finds the class with the specified name, loading it using the system - * class loader if necessary. - * - * @param className - * the name of the class to look for. - * @return the {@code Class} object with the requested {@code className}. - * @throws ClassNotFoundException - * if the class can not be found. - */ - protected final Class<?> findSystemClass(String className) throws ClassNotFoundException { - return Class.forName(className, false, getSystemClassLoader()); - } - - /** - * Returns this class loader's parent. - * - * @return this class loader's parent or {@code null}. - */ - public final ClassLoader getParent() { - return parent; - } - - /** - * Returns the URL of the resource with the specified name. This - * implementation first tries to use the parent class loader to find the - * resource; if this fails then {@link #findResource(String)} is called to - * find the requested resource. - * - * @param resName - * the name of the resource to find. - * @return the {@code URL} object for the requested resource or {@code null} - * if the resource can not be found - * @see Class#getResource - */ - public URL getResource(String resName) { - URL resource = parent.getResource(resName); - if (resource == null) { - resource = findResource(resName); - } - return resource; - } - - /** - * Returns an enumeration of URLs for the resource with the specified name. - * This implementation first uses this class loader's parent to find the - * resource, then it calls {@link #findResources(String)} to get additional - * URLs. The returned enumeration contains the {@code URL} objects of both - * find operations. - * - * @return an enumeration of {@code URL} objects for the requested resource. - * @param resName - * the name of the resource to find. - * @throws IOException - * if an I/O error occurs. - */ - @SuppressWarnings("unchecked") - public Enumeration<URL> getResources(String resName) throws IOException { - - Enumeration first = parent.getResources(resName); - Enumeration second = findResources(resName); - - return new TwoEnumerationsInOne(first, second); - } - - /** - * Returns a stream for the resource with the specified name. See - * {@link #getResource(String)} for a description of the lookup algorithm - * used to find the resource. - * - * @return a stream for the resource or {@code null} if the resource can not be found - * @param resName - * the name of the resource to find. - * @see Class#getResourceAsStream - */ - public InputStream getResourceAsStream(String resName) { - try { - URL url = getResource(resName); - if (url != null) { - return url.openStream(); - } - } catch (IOException ex) { - // Don't want to see the exception. - } - - return null; - } - - /** - * Loads the class with the specified name. Invoking this method is - * equivalent to calling {@code loadClass(className, false)}. - * <p> - * <strong>Note:</strong> In the Android reference implementation, the - * second parameter of {@link #loadClass(String, boolean)} is ignored - * anyway. - * </p> - * - * @return the {@code Class} object. - * @param className - * the name of the class to look for. - * @throws ClassNotFoundException - * if the class can not be found. - */ - public Class<?> loadClass(String className) throws ClassNotFoundException { - return loadClass(className, false); - } - - /** - * Loads the class with the specified name, optionally linking it after - * loading. The following steps are performed: - * <ol> - * <li> Call {@link #findLoadedClass(String)} to determine if the requested - * class has already been loaded.</li> - * <li>If the class has not yet been loaded: Invoke this method on the - * parent class loader.</li> - * <li>If the class has still not been loaded: Call - * {@link #findClass(String)} to find the class.</li> - * </ol> - * <p> - * <strong>Note:</strong> In the Android reference implementation, the - * {@code resolve} parameter is ignored; classes are never linked. - * </p> - * - * @return the {@code Class} object. - * @param className - * the name of the class to look for. - * @param resolve - * Indicates if the class should be resolved after loading. This - * parameter is ignored on the Android reference implementation; - * classes are not resolved. - * @throws ClassNotFoundException - * if the class can not be found. - */ - protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException { - Class<?> clazz = findLoadedClass(className); - - if (clazz == null) { - try { - clazz = parent.loadClass(className, false); - } catch (ClassNotFoundException e) { - // Don't want to see this. - } - - if (clazz == null) { - clazz = findClass(className); - } - } - - return clazz; - } - - /** - * Forces a class to be linked (initialized). If the class has already been - * linked this operation has no effect. - * <p> - * <strong>Note:</strong> In the Android reference implementation, this - * method has no effect. - * </p> - * - * @param clazz - * the class to link. - */ - protected final void resolveClass(Class<?> clazz) { - // no-op, doesn't make sense on android. - } - - /** - * Finds the URL of the resource with the specified name. This - * implementation just returns {@code null}; it should be overridden in - * subclasses. - * - * @param resName - * the name of the resource to find. - * @return the {@code URL} object for the requested resource. - */ - protected URL findResource(String resName) { - return null; - } - - /** - * Finds an enumeration of URLs for the resource with the specified name. - * This implementation just returns an empty {@code Enumeration}; it should - * be overridden in subclasses. - * - * @param resName - * the name of the resource to find. - * @return an enumeration of {@code URL} objects for the requested resource. - * @throws IOException - * if an I/O error occurs. - */ - @SuppressWarnings( { - "unchecked", "unused" - }) - protected Enumeration<URL> findResources(String resName) throws IOException { - return Collections.emptyEnumeration(); - } - - /** - * Returns the absolute path of the native library with the specified name, - * or {@code null}. If this method returns {@code null} then the virtual - * machine searches the directories specified by the system property - * "java.library.path". - * <p> - * This implementation always returns {@code null}. - * </p> - * - * @param libName - * the name of the library to find. - * @return the absolute path of the library. - */ - protected String findLibrary(String libName) { - return null; - } - - /** - * Returns the package with the specified name. Package information is - * searched in this class loader. - * - * @param name - * the name of the package to find. - * @return the package with the requested name; {@code null} if the package - * can not be found. - */ - protected Package getPackage(String name) { - synchronized (packages) { - return packages.get(name); - } - } - - /** - * Returns all the packages known to this class loader. - * - * @return an array with all packages known to this class loader. - */ - protected Package[] getPackages() { - synchronized (packages) { - Collection<Package> col = packages.values(); - Package[] result = new Package[col.size()]; - col.toArray(result); - return result; - } - } - - /** - * Defines and returns a new {@code Package} using the specified - * information. If {@code sealBase} is {@code null}, the package is left - * unsealed. Otherwise, the package is sealed using this URL. - * - * @param name - * the name of the package. - * @param specTitle - * the title of the specification. - * @param specVersion - * the version of the specification. - * @param specVendor - * the vendor of the specification. - * @param implTitle - * the implementation title. - * @param implVersion - * the implementation version. - * @param implVendor - * the specification vendor. - * @param sealBase - * the URL used to seal this package or {@code null} to leave the - * package unsealed. - * @return the {@code Package} object that has been created. - * @throws IllegalArgumentException - * if a package with the specified name already exists. - */ - protected Package definePackage(String name, String specTitle, String specVersion, - String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase) - throws IllegalArgumentException { - - synchronized (packages) { - if (packages.containsKey(name)) { - throw new IllegalArgumentException("Package " + name + " already defined"); - } - - Package newPackage = new Package(name, specTitle, specVersion, specVendor, implTitle, - implVersion, implVendor, sealBase); - - packages.put(name, newPackage); - - return newPackage; - } - } - - /** - * Sets the signers of the specified class. This implementation does - * nothing. - * - * @param c - * the {@code Class} object for which to set the signers. - * @param signers - * the signers for {@code c}. - */ - protected final void setSigners(Class<?> c, Object[] signers) { - } - - /** - * Sets the assertion status of the class with the specified name. - * <p> - * <strong>Note: </strong>This method does nothing in the Android reference - * implementation. - * </p> - * - * @param cname - * the name of the class for which to set the assertion status. - * @param enable - * the new assertion status. - */ - public void setClassAssertionStatus(String cname, boolean enable) { - } - - /** - * Sets the assertion status of the package with the specified name. - * <p> - * <strong>Note: </strong>This method does nothing in the Android reference - * implementation. - * </p> - * - * @param pname - * the name of the package for which to set the assertion status. - * @param enable - * the new assertion status. - */ - public void setPackageAssertionStatus(String pname, boolean enable) { - } - - /** - * Sets the default assertion status for this class loader. - * <p> - * <strong>Note: </strong>This method does nothing in the Android reference - * implementation. - * </p> - * - * @param enable - * the new assertion status. - */ - public void setDefaultAssertionStatus(boolean enable) { - } - - /** - * Sets the default assertion status for this class loader to {@code false} - * and removes any package default and class assertion status settings. - * <p> - * <strong>Note:</strong> This method does nothing in the Android reference - * implementation. - * </p> - */ - public void clearAssertionStatus() { - } -} - -/* - * Provides a helper class that combines two existing URL enumerations into one. - * It is required for the getResources() methods. Items are fetched from the - * first enumeration until it's empty, then from the second one. - */ -class TwoEnumerationsInOne implements Enumeration<URL> { - - private Enumeration<URL> first; - - private Enumeration<URL> second; - - public TwoEnumerationsInOne(Enumeration<URL> first, Enumeration<URL> second) { - this.first = first; - this.second = second; - } - - public boolean hasMoreElements() { - return first.hasMoreElements() || second.hasMoreElements(); - } - - public URL nextElement() { - if (first.hasMoreElements()) { - return first.nextElement(); - } else { - return second.nextElement(); - } - } - -} - -/** - * Provides an explicit representation of the boot class loader. It sits at the - * head of the class loader chain and delegates requests to the VM's internal - * class loading mechanism. - */ -class BootClassLoader extends ClassLoader { - - private static BootClassLoader instance; - - @FindBugsSuppressWarnings("DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED") - public static synchronized BootClassLoader getInstance() { - if (instance == null) { - instance = new BootClassLoader(); - } - - return instance; - } - - public BootClassLoader() { - super(null, true); - } - - @Override - protected Class<?> findClass(String name) throws ClassNotFoundException { - return VMClassLoader.loadClass(name, false); - } - - @Override - protected URL findResource(String name) { - return VMClassLoader.getResource(name); - } - - @SuppressWarnings("unused") - @Override - protected Enumeration<URL> findResources(String resName) throws IOException { - return Collections.enumeration(VMClassLoader.getResources(resName)); - } - - /** - * Returns package information for the given package. Unfortunately, the - * Android BootClassLoader doesn't really have this information, and as a - * non-secure ClassLoader, it isn't even required to, according to the spec. - * Yet, we want to provide it, in order to make all those hopeful callers of - * {@code myClass.getPackage().getName()} happy. Thus we construct a Package - * object the first time it is being requested and fill most of the fields - * with dummy values. The Package object is then put into the ClassLoader's - * Package cache, so we see the same one next time. We don't create Package - * objects for null arguments or for the default package. - * <p> - * There a limited chance that we end up with multiple Package objects - * representing the same package: It can happen when when a package is - * scattered across different JAR files being loaded by different - * ClassLoaders. Rather unlikely, and given that this whole thing is more or - * less a workaround, probably not worth the effort. - */ - @Override - protected Package getPackage(String name) { - if (name != null && !name.isEmpty()) { - synchronized (this) { - Package pack = super.getPackage(name); - - if (pack == null) { - pack = definePackage(name, "Unknown", "0.0", "Unknown", "Unknown", "0.0", - "Unknown", null); - } - - return pack; - } - } - - return null; - } - - @Override - public URL getResource(String resName) { - return findResource(resName); - } - - @Override - protected Class<?> loadClass(String className, boolean resolve) - throws ClassNotFoundException { - Class<?> clazz = findLoadedClass(className); - - if (clazz == null) { - clazz = findClass(className); - } - - return clazz; - } - - @Override - public Enumeration<URL> getResources(String resName) throws IOException { - return findResources(resName); - } -} - -/** - * TODO Open issues - Missing / empty methods - Signer stuff - Protection - * domains - Assertions - */ diff --git a/libdvm/src/main/java/java/lang/Daemons.java b/libdvm/src/main/java/java/lang/Daemons.java deleted file mode 100644 index 78a4152..0000000 --- a/libdvm/src/main/java/java/lang/Daemons.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (C) 2011 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; - -import dalvik.system.VMRuntime; -import java.lang.ref.FinalizerReference; -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.util.concurrent.TimeoutException; -import libcore.util.EmptyArray; - -/** - * Calls Object.finalize() on objects in the finalizer reference queue. The VM - * will abort if any finalize() call takes more than the maximum finalize time - * to complete. - * - * @hide - */ -public final class Daemons { - private static final int NANOS_PER_MILLI = 1000 * 1000; - private static final int NANOS_PER_SECOND = NANOS_PER_MILLI * 1000; - private static final long MAX_FINALIZE_NANOS = 10L * NANOS_PER_SECOND; - - public static void start() { - ReferenceQueueDaemon.INSTANCE.start(); - FinalizerDaemon.INSTANCE.start(); - FinalizerWatchdogDaemon.INSTANCE.start(); - } - - public static void stop() { - ReferenceQueueDaemon.INSTANCE.stop(); - FinalizerDaemon.INSTANCE.stop(); - FinalizerWatchdogDaemon.INSTANCE.stop(); - } - - /** - * A background task that provides runtime support to the application. - * Daemons can be stopped and started, but only so that the zygote can be a - * single-threaded process when it forks. - */ - private static abstract class Daemon implements Runnable { - private Thread thread; - - public synchronized void start() { - if (thread != null) { - throw new IllegalStateException("already running"); - } - thread = new Thread(ThreadGroup.mSystem, this, - getClass().getSimpleName()); - thread.setDaemon(true); - thread.start(); - } - - public abstract void run(); - - /** - * Returns true while the current thread should continue to run; false - * when it should return. - */ - protected synchronized boolean isRunning() { - return thread != null; - } - - public synchronized void interrupt() { - if (thread == null) { - throw new IllegalStateException("not running"); - } - thread.interrupt(); - } - - /** - * Waits for the runtime thread to stop. This interrupts the thread - * currently running the runnable and then waits for it to exit. - */ - public void stop() { - Thread threadToStop; - synchronized (this) { - threadToStop = thread; - thread = null; - } - if (threadToStop == null) { - throw new IllegalStateException("not running"); - } - threadToStop.interrupt(); - while (true) { - try { - threadToStop.join(); - return; - } catch (InterruptedException ignored) { - } - } - } - - /** - * Returns the current stack trace of the thread, or an empty stack trace - * if the thread is not currently running. - */ - public synchronized StackTraceElement[] getStackTrace() { - return thread != null ? thread.getStackTrace() : EmptyArray.STACK_TRACE_ELEMENT; - } - } - - /** - * This heap management thread moves elements from the garbage collector's - * pending list to the managed reference queue. - */ - private static class ReferenceQueueDaemon extends Daemon { - private static final ReferenceQueueDaemon INSTANCE = new ReferenceQueueDaemon(); - - @Override public void run() { - while (isRunning()) { - Reference<?> list; - try { - synchronized (ReferenceQueue.class) { - while (ReferenceQueue.unenqueued == null) { - ReferenceQueue.class.wait(); - } - list = ReferenceQueue.unenqueued; - ReferenceQueue.unenqueued = null; - } - } catch (InterruptedException e) { - continue; - } - enqueue(list); - } - } - - 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(); - } - } - } - - private static class FinalizerDaemon extends Daemon { - private static final FinalizerDaemon INSTANCE = new FinalizerDaemon(); - private final ReferenceQueue<Object> queue = FinalizerReference.queue; - private volatile Object finalizingObject; - private volatile long finalizingStartedNanos; - - @Override public void run() { - while (isRunning()) { - // Take a reference, blocking until one is ready or the thread should stop - try { - doFinalize((FinalizerReference<?>) queue.remove()); - } catch (InterruptedException ignored) { - } - } - } - - @FindBugsSuppressWarnings("FI_EXPLICIT_INVOCATION") - private void doFinalize(FinalizerReference<?> reference) { - FinalizerReference.remove(reference); - Object object = reference.get(); - reference.clear(); - try { - finalizingStartedNanos = System.nanoTime(); - finalizingObject = object; - synchronized (FinalizerWatchdogDaemon.INSTANCE) { - FinalizerWatchdogDaemon.INSTANCE.notify(); - } - object.finalize(); - } catch (Throwable ex) { - // The RI silently swallows these, but Android has always logged. - System.logE("Uncaught exception thrown by finalizer", ex); - } finally { - finalizingObject = null; - } - } - } - - /** - * The watchdog exits the VM if the finalizer ever gets stuck. We consider - * the finalizer to be stuck if it spends more than MAX_FINALIZATION_MILLIS - * on one instance. - */ - private static class FinalizerWatchdogDaemon extends Daemon { - private static final FinalizerWatchdogDaemon INSTANCE = new FinalizerWatchdogDaemon(); - - @Override public void run() { - while (isRunning()) { - Object object = waitForObject(); - if (object == null) { - // We have been interrupted, need to see if this daemon has been stopped. - continue; - } - boolean finalized = waitForFinalization(object); - if (!finalized && !VMRuntime.getRuntime().isDebuggerActive()) { - finalizerTimedOut(object); - break; - } - } - } - - private Object waitForObject() { - while (true) { - Object object = FinalizerDaemon.INSTANCE.finalizingObject; - if (object != null) { - return object; - } - synchronized (this) { - // wait until something is ready to be finalized - // http://code.google.com/p/android/issues/detail?id=22778 - try { - wait(); - } catch (InterruptedException e) { - // Daemon.stop may have interrupted us. - return null; - } - } - } - } - - private void sleepFor(long startNanos, long durationNanos) { - while (true) { - long elapsedNanos = System.nanoTime() - startNanos; - long sleepNanos = durationNanos - elapsedNanos; - long sleepMills = sleepNanos / NANOS_PER_MILLI; - if (sleepMills <= 0) { - return; - } - try { - Thread.sleep(sleepMills); - } catch (InterruptedException e) { - if (!isRunning()) { - return; - } - } - } - } - - private boolean waitForFinalization(Object object) { - sleepFor(FinalizerDaemon.INSTANCE.finalizingStartedNanos, MAX_FINALIZE_NANOS); - return object != FinalizerDaemon.INSTANCE.finalizingObject; - } - - private static void finalizerTimedOut(Object object) { - // The current object has exceeded the finalization deadline; abort! - String message = object.getClass().getName() + ".finalize() timed out after " - + (MAX_FINALIZE_NANOS / NANOS_PER_SECOND) + " seconds"; - Exception syntheticException = new TimeoutException(message); - // We use the stack from where finalize() was running to show where it was stuck. - syntheticException.setStackTrace(FinalizerDaemon.INSTANCE.getStackTrace()); - Thread.UncaughtExceptionHandler h = Thread.getDefaultUncaughtExceptionHandler(); - if (h == null) { - // If we have no handler, log and exit. - System.logE(message, syntheticException); - System.exit(2); - } - // Otherwise call the handler to do crash reporting. - // We don't just throw because we're not the thread that - // timed out; we're the thread that detected it. - h.uncaughtException(Thread.currentThread(), syntheticException); - } - } -} diff --git a/libdvm/src/main/java/java/lang/Enum.java b/libdvm/src/main/java/java/lang/Enum.java deleted file mode 100644 index 4b897aa..0000000 --- a/libdvm/src/main/java/java/lang/Enum.java +++ /dev/null @@ -1,221 +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. - */ - -package java.lang; - -import java.io.Serializable; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import libcore.util.BasicLruCache; -import libcore.util.EmptyArray; - -/** - * The superclass of all enumerated types. Actual enumeration types inherit from - * this class, but extending this class does not make a class an enumeration - * type, since the compiler needs to generate special information for it. - */ -public abstract class Enum<E extends Enum<E>> implements Serializable, Comparable<E> { - - private static final long serialVersionUID = -4300926546619394005L; - - private static final BasicLruCache<Class<? extends Enum>, Object[]> sharedConstantsCache - = new BasicLruCache<Class<? extends Enum>, Object[]>(64) { - @Override protected Object[] create(Class<? extends Enum> enumType) { - if (!enumType.isEnum()) { - return null; - } - Method method = (Method) Class.getDeclaredConstructorOrMethod( - enumType, "values", EmptyArray.CLASS); - try { - return (Object[]) method.invoke((Object[]) null); - } catch (IllegalAccessException impossible) { - throw new AssertionError(); - } catch (InvocationTargetException impossible) { - throw new AssertionError(); - } - } - }; - - private final String name; - - private final int ordinal; - - /** - * Constructor for constants of enum subtypes. - * - * @param name - * the enum constant's declared name. - * @param ordinal - * the enum constant's ordinal, which corresponds to its position - * in the enum declaration, starting at zero. - */ - protected Enum(String name, int ordinal) { - this.name = name; - this.ordinal = ordinal; - } - - /** - * Returns the name of this enum constant. The name is the field as it - * appears in the {@code enum} declaration. - * - * @return the name of this enum constant. - * @see #toString() - */ - public final String name() { - return name; - } - - /** - * Returns the position of the enum constant in the declaration. The first - * constant has an ordinal value of zero. - * - * @return the ordinal value of this enum constant. - */ - public final int ordinal() { - return ordinal; - } - - /** - * Returns a string containing a concise, human-readable description of this - * object. In this case, the enum constant's name is returned. - * - * @return a printable representation of this object. - */ - @Override - public String toString() { - return name; - } - - /** - * Compares this object with the specified object and indicates if they are - * equal. In order to be equal, {@code object} must be identical to this - * enum constant. - * - * @param other - * the object to compare this enum constant with. - * @return {@code true} if the specified object is equal to this - * {@code Enum}; {@code false} otherwise. - */ - @Override - public final boolean equals(Object other) { - return this == other; - } - - @Override - public final int hashCode() { - return ordinal + (name == null ? 0 : name.hashCode()); - } - - /** - * {@code Enum} objects are singletons, they may not be cloned. This method - * always throws a {@code CloneNotSupportedException}. - * - * @return does not return. - * @throws CloneNotSupportedException - * is always thrown. - */ - @Override - protected final Object clone() throws CloneNotSupportedException { - throw new CloneNotSupportedException("Enums may not be cloned"); - } - - /** - * Compares this object to the specified enum object to determine their - * relative order. This method compares the object's ordinal values, that - * is, their position in the enum declaration. - * - * @param o - * the enum object to compare this object to. - * @return a negative value if the ordinal value of this enum constant is - * less than the ordinal value of {@code o}; 0 if the ordinal - * values of this enum constant and {@code o} are equal; a positive - * value if the ordinal value of this enum constant is greater than - * the ordinal value of {@code o}. - * @see java.lang.Comparable - */ - public final int compareTo(E o) { - return ordinal - o.ordinal(); - } - - /** - * Returns the enum constant's declaring class. - * - * @return the class object representing the constant's enum type. - */ - @SuppressWarnings("unchecked") - public final Class<E> getDeclaringClass() { - Class<?> myClass = getClass(); - Class<?> mySuperClass = myClass.getSuperclass(); - if (Enum.class == mySuperClass) { - return (Class<E>)myClass; - } - return (Class<E>)mySuperClass; - } - - /** - * Returns the constant with the specified name of the specified enum type. - * - * @param enumType - * the class of the enumerated type to search for the constant - * value. - * @param name - * the name of the constant value to find. - * @return the enum constant. - * @throws NullPointerException - * if either {@code enumType} or {@code name} are {@code null}. - * @throws IllegalArgumentException - * if {@code enumType} is not an enumerated type or does not - * have a constant value called {@code name}. - */ - public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) { - if (enumType == null) { - throw new NullPointerException("enumType == null"); - } else if (name == null) { - throw new NullPointerException("name == null"); - } - T[] values = getSharedConstants(enumType); - if (values == null) { - throw new IllegalArgumentException(enumType + " is not an enum type"); - } - for (T value : values) { - if (name.equals(value.name())) { - return value; - } - } - throw new IllegalArgumentException(name + " is not a constant in " + enumType.getName()); - } - - /** - * Returns a shared, mutable array containing the constants of this enum. It - * is an error to modify the returned array. - * - * @hide - */ - @SuppressWarnings("unchecked") // the cache always returns the type matching enumType - public static <T extends Enum<T>> T[] getSharedConstants(Class<T> enumType) { - return (T[]) sharedConstantsCache.get(enumType); - } - - /** - * Enum types may not have finalizers. - * - * @since 1.6 - */ - @Override - @SuppressWarnings("FinalizeDoesntCallSuperFinalize") - protected final void finalize() { - } -} diff --git a/libdvm/src/main/java/java/lang/Object.java b/libdvm/src/main/java/java/lang/Object.java deleted file mode 100644 index d2cd2f1..0000000 --- a/libdvm/src/main/java/java/lang/Object.java +++ /dev/null @@ -1,443 +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; - -/** - * The root class of the Java class hierarchy. All non-primitive types - * (including arrays) inherit either directly or indirectly from this class. - * - * <a name="writing_equals"><h4>Writing a correct {@code equals} method</h4></a> - * <p>Follow this style to write a canonical {@code equals} method: - * <pre> - * // Use @Override to avoid accidental overloading. - * @Override public boolean equals(Object o) { - * // Return true if the objects are identical. - * // (This is just an optimization, not required for correctness.) - * if (this == o) { - * return true; - * } - * - * // Return false if the other object has the wrong type. - * // This type may be an interface depending on the interface's specification. - * if (!(o instanceof MyType)) { - * return false; - * } - * - * // Cast to the appropriate type. - * // This will succeed because of the instanceof, and lets us access private fields. - * MyType lhs = (MyType) o; - * - * // Check each field. Primitive fields, reference fields, and nullable reference - * // fields are all treated differently. - * return primitiveField == lhs.primitiveField && - * referenceField.equals(lhs.referenceField) && - * (nullableField == null ? lhs.nullableField == null - * : nullableField.equals(lhs.nullableField)); - * } - * </pre> - * <p>If you override {@code equals}, you should also override {@code hashCode}: equal - * instances must have equal hash codes. - * - * <p>See <i>Effective Java</i> item 8 for much more detail and clarification. - * - * <a name="writing_hashCode"><h4>Writing a correct {@code hashCode} method</h4></a> - * <p>Follow this style to write a canonical {@code hashCode} method: - * <pre> - * @Override public int hashCode() { - * // Start with a non-zero constant. - * int result = 17; - * - * // Include a hash for each field. - * result = 31 * result + (booleanField ? 1 : 0); - * - * result = 31 * result + byteField; - * result = 31 * result + charField; - * result = 31 * result + shortField; - * result = 31 * result + intField; - * - * result = 31 * result + (int) (longField ^ (longField >>> 32)); - * - * result = 31 * result + Float.floatToIntBits(floatField); - * - * long doubleFieldBits = Double.doubleToLongBits(doubleField); - * result = 31 * result + (int) (doubleFieldBits ^ (doubleFieldBits >>> 32)); - * - * result = 31 * result + Arrays.hashCode(arrayField); - * - * result = 31 * result + referenceField.hashCode(); - * result = 31 * result + - * (nullableReferenceField == null ? 0 - * : nullableReferenceField.hashCode()); - * - * return result; - * } - * </pre> - * - * <p>If you don't intend your type to be used as a hash key, don't simply rely on the default - * {@code hashCode} implementation, because that silently and non-obviously breaks any future - * code that does use your type as a hash key. You should throw instead: - * <pre> - * @Override public int hashCode() { - * throw new UnsupportedOperationException(); - * } - * </pre> - * - * <p>See <i>Effective Java</i> item 9 for much more detail and clarification. - * - * <a name="writing_toString"><h4>Writing a useful {@code toString} method</h4></a> - * <p>For debugging convenience, it's common to override {@code toString} in this style: - * <pre> - * @Override public String toString() { - * return getClass().getName() + "[" + - * "primitiveField=" + primitiveField + ", " + - * "referenceField=" + referenceField + ", " + - * "arrayField=" + Arrays.toString(arrayField) + "]"; - * } - * </pre> - * <p>The set of fields to include is generally the same as those that would be tested - * in your {@code equals} implementation. - * <p>See <i>Effective Java</i> item 10 for much more detail and clarification. - */ -public class Object { - /** - * Constructs a new instance of {@code Object}. - */ - public Object() { - } - - /** - * Creates and returns a copy of this {@code Object}. The default - * implementation returns a so-called "shallow" copy: It creates a new - * instance of the same class and then copies the field values (including - * object references) from this instance to the new instance. A "deep" copy, - * in contrast, would also recursively clone nested objects. A subclass that - * needs to implement this kind of cloning should call {@code super.clone()} - * to create the new instance and then create deep copies of the nested, - * mutable objects. - * - * @return a copy of this object. - * @throws CloneNotSupportedException - * if this object's class does not implement the {@code - * Cloneable} interface. - */ - protected Object clone() throws CloneNotSupportedException { - if (!(this instanceof Cloneable)) { - throw new CloneNotSupportedException("Class doesn't implement Cloneable"); - } - - return internalClone((Cloneable) this); - } - - /* - * Native helper method for cloning. - */ - private native Object internalClone(Cloneable o); - - /** - * Compares this instance with the specified object and indicates if they - * are equal. In order to be equal, {@code o} must represent the same object - * as this instance using a class-specific comparison. The general contract - * is that this comparison should be reflexive, symmetric, and transitive. - * Also, no object reference other than null is equal to null. - * - * <p>The default implementation returns {@code true} only if {@code this == - * o}. See <a href="{@docRoot}reference/java/lang/Object.html#writing_equals">Writing a correct - * {@code equals} method</a> - * if you intend implementing your own {@code equals} method. - * - * <p>The general contract for the {@code equals} and {@link - * #hashCode()} methods is that if {@code equals} returns {@code true} for - * any two objects, then {@code hashCode()} must return the same value for - * these objects. This means that subclasses of {@code Object} usually - * override either both methods or neither of them. - * - * @param o - * the object to compare this instance with. - * @return {@code true} if the specified object is equal to this {@code - * Object}; {@code false} otherwise. - * @see #hashCode - */ - public boolean equals(Object o) { - return this == o; - } - - /** - * Invoked when the garbage collector has detected that this instance is no longer reachable. - * The default implementation does nothing, but this method can be overridden to free resources. - * - * <p>Note that objects that override {@code finalize} are significantly more expensive than - * objects that don't. Finalizers may be run a long time after the object is no longer - * reachable, depending on memory pressure, so it's a bad idea to rely on them for cleanup. - * Note also that finalizers are run on a single VM-wide finalizer thread, - * so doing blocking work in a finalizer is a bad idea. A finalizer is usually only necessary - * for a class that has a native peer and needs to call a native method to destroy that peer. - * Even then, it's better to provide an explicit {@code close} method (and implement - * {@link java.io.Closeable}), and insist that callers manually dispose of instances. This - * works well for something like files, but less well for something like a {@code BigInteger} - * where typical calling code would have to deal with lots of temporaries. Unfortunately, - * code that creates lots of temporaries is the worst kind of code from the point of view of - * the single finalizer thread. - * - * <p>If you <i>must</i> use finalizers, consider at least providing your own - * {@link java.lang.ref.ReferenceQueue} and having your own thread process that queue. - * - * <p>Unlike constructors, finalizers are not automatically chained. You are responsible for - * calling {@code super.finalize()} yourself. - * - * <p>Uncaught exceptions thrown by finalizers are ignored and do not terminate the finalizer - * thread. - * - * See <i>Effective Java</i> Item 7, "Avoid finalizers" for more. - */ - @FindBugsSuppressWarnings("FI_EMPTY") - protected void finalize() throws Throwable { - } - - /** - * Returns the unique instance of {@link Class} that represents this - * object's class. Note that {@code getClass()} is a special case in that it - * actually returns {@code Class<? extends Foo>} where {@code Foo} is the - * erasure of the type of the expression {@code getClass()} was called upon. - * <p> - * As an example, the following code actually compiles, although one might - * think it shouldn't: - * <p> - * <pre>{@code - * List<Integer> l = new ArrayList<Integer>(); - * Class<? extends List> c = l.getClass();}</pre> - * - * @return this object's {@code Class} instance. - */ - public final native Class<?> getClass(); - - /** - * Returns an integer hash code for this object. By contract, any two - * objects for which {@link #equals} returns {@code true} must return - * the same hash code value. This means that subclasses of {@code Object} - * usually override both methods or neither method. - * - * <p>Note that hash values must not change over time unless information used in equals - * comparisons also changes. - * - * <p>See <a href="{@docRoot}reference/java/lang/Object.html#writing_hashCode">Writing a correct - * {@code hashCode} method</a> - * if you intend implementing your own {@code hashCode} method. - * - * @return this object's hash code. - * @see #equals - */ - public native int hashCode(); - - /** - * Causes a thread which is waiting on this object's monitor (by means of - * calling one of the {@code wait()} methods) to be woken up. If more than - * one thread is waiting, one of them is chosen at the discretion of the - * VM. The chosen thread will not run immediately. The thread - * that called {@code notify()} has to release the object's monitor first. - * Also, the chosen thread still has to compete against other threads that - * try to synchronize on the same object. - * - * <p>This method can only be invoked by a thread which owns this object's - * monitor. A thread becomes owner of an object's monitor - * <ul> - * <li>by executing a synchronized method of that object;</li> - * <li>by executing the body of a {@code synchronized} statement that - * synchronizes on the object;</li> - * <li>by executing a synchronized static method if the object is of type - * {@code Class}.</li> - * </ul> - * - * @see #notifyAll - * @see #wait() - * @see #wait(long) - * @see #wait(long,int) - * @see java.lang.Thread - */ - public final native void notify(); - - /** - * Causes all threads which are waiting on this object's monitor (by means - * of calling one of the {@code wait()} methods) to be woken up. The threads - * will not run immediately. The thread that called {@code notify()} has to - * release the object's monitor first. Also, the threads still have to - * compete against other threads that try to synchronize on the same object. - * - * <p>This method can only be invoked by a thread which owns this object's - * monitor. A thread becomes owner of an object's monitor - * <ul> - * <li>by executing a synchronized method of that object;</li> - * <li>by executing the body of a {@code synchronized} statement that - * synchronizes on the object;</li> - * <li>by executing a synchronized static method if the object is of type - * {@code Class}.</li> - * </ul> - * - * @throws IllegalMonitorStateException - * if the thread calling this method is not the owner of this - * object's monitor. - * @see #notify - * @see #wait() - * @see #wait(long) - * @see #wait(long,int) - * @see java.lang.Thread - */ - public final native void notifyAll(); - - /** - * Returns a string containing a concise, human-readable description of this - * object. Subclasses are encouraged to override this method and provide an - * implementation that takes into account the object's type and data. The - * default implementation is equivalent to the following expression: - * <pre> - * getClass().getName() + '@' + Integer.toHexString(hashCode())</pre> - * <p>See <a href="{@docRoot}reference/java/lang/Object.html#writing_toString">Writing a useful - * {@code toString} method</a> - * if you intend implementing your own {@code toString} method. - * - * @return a printable representation of this object. - */ - public String toString() { - return getClass().getName() + '@' + Integer.toHexString(hashCode()); - } - - /** - * Causes the calling thread to wait until another thread calls the {@code - * notify()} or {@code notifyAll()} method of this object. This method can - * only be invoked by a thread which owns this object's monitor; see - * {@link #notify()} on how a thread can become the owner of a monitor. - * - * <p>A waiting thread can be sent {@code interrupt()} to cause it to - * prematurely stop waiting, so {@code wait} should be called in a loop to - * check that the condition that has been waited for has been met before - * continuing. - * - * <p>While the thread waits, it gives up ownership of this object's - * monitor. When it is notified (or interrupted), it re-acquires the monitor - * before it starts running. - * - * @throws IllegalMonitorStateException - * if the thread calling this method is not the owner of this - * object's monitor. - * @throws InterruptedException if the current thread has been interrupted. - * The interrupted status of the current thread will be cleared before the exception - * is thrown. - * @see #notify - * @see #notifyAll - * @see #wait(long) - * @see #wait(long,int) - * @see java.lang.Thread - */ - public final void wait() throws InterruptedException { - wait(0, 0); - } - - /** - * Causes the calling thread to wait until another thread calls the {@code - * notify()} or {@code notifyAll()} method of this object or until the - * specified timeout expires. This method can only be invoked by a thread - * which owns this object's monitor; see {@link #notify()} on how a thread - * can become the owner of a monitor. - * - * <p>A waiting thread can be sent {@code interrupt()} to cause it to - * prematurely stop waiting, so {@code wait} should be called in a loop to - * check that the condition that has been waited for has been met before - * continuing. - * - * <p>While the thread waits, it gives up ownership of this object's - * monitor. When it is notified (or interrupted), it re-acquires the monitor - * before it starts running. - * - * <p>A timeout of zero means the calling thread should wait forever unless interrupted or - * notified. - * - * @param millis - * the maximum time to wait in milliseconds. - * @throws IllegalArgumentException - * if {@code millis < 0}. - * @throws IllegalMonitorStateException - * if the thread calling this method is not the owner of this - * object's monitor. - * @throws InterruptedException if the current thread has been interrupted. - * The interrupted status of the current thread will be cleared before the exception - * is thrown. - * @see #notify - * @see #notifyAll - * @see #wait() - * @see #wait(long,int) - * @see java.lang.Thread - */ - public final void wait(long millis) throws InterruptedException { - wait(millis, 0); - } - - /** - * Causes the calling thread to wait until another thread calls the {@code - * notify()} or {@code notifyAll()} method of this object or until the - * specified timeout expires. This method can only be invoked by a thread - * that owns this object's monitor; see {@link #notify()} on how a thread - * can become the owner of a monitor. - * - * <p>A waiting thread can be sent {@code interrupt()} to cause it to - * prematurely stop waiting, so {@code wait} should be called in a loop to - * check that the condition that has been waited for has been met before - * continuing. - * - * <p>While the thread waits, it gives up ownership of this object's - * monitor. When it is notified (or interrupted), it re-acquires the monitor - * before it starts running. - * - * <p>A timeout of zero means the calling thread should wait forever unless interrupted or - * notified. - * - * @param millis - * the maximum time to wait in milliseconds. - * @param nanos - * the fraction of a millisecond to wait, specified in - * nanoseconds. - * @throws IllegalArgumentException - * if {@code millis < 0}, {@code nanos < 0} or {@code nanos > - * 999999}. - * @throws IllegalMonitorStateException - * if the thread calling this method is not the owner of this - * object's monitor. - * @throws InterruptedException if the current thread has been interrupted. - * The interrupted status of the current thread will be cleared before the exception - * is thrown. - * @see #notify - * @see #notifyAll - * @see #wait() - * @see #wait(long,int) - * @see java.lang.Thread - */ - public final native void wait(long millis, int nanos) throws InterruptedException; -} diff --git a/libdvm/src/main/java/java/lang/String.java b/libdvm/src/main/java/java/lang/String.java deleted file mode 100644 index 10a6301..0000000 --- a/libdvm/src/main/java/java/lang/String.java +++ /dev/null @@ -1,2075 +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. - */ - -package java.lang; - -import java.io.Serializable; -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.EmptyArray; - -/** - * An immutable sequence of characters/code units ({@code char}s). A - * {@code String} is represented by array of UTF-16 values, such that - * Unicode supplementary characters (code points) are stored/encoded as - * surrogate pairs via Unicode code units ({@code char}). - * - * <a name="backing_array"><h3>Backing Arrays</h3></a> - * This class is implemented using a char[]. The length of the array may exceed - * the length of the string. For example, the string "Hello" may be backed by - * the array {@code ['H', 'e', 'l', 'l', 'o', 'W'. 'o', 'r', 'l', 'd']} with - * offset 0 and length 5. - * - * <p>Multiple strings can share the same char[] because strings are immutable. - * The {@link #substring} method <strong>always</strong> returns a string that - * shares the backing array of its source string. Generally this is an - * optimization: fewer character arrays need to be allocated, and less copying - * is necessary. But this can also lead to unwanted heap retention. Taking a - * short substring of long string means that the long shared char[] won't be - * garbage until both strings are garbage. This typically happens when parsing - * small substrings out of a large input. To avoid this where necessary, call - * {@code new String(longString.subString(...))}. The string copy constructor - * always ensures that the backing array is no larger than necessary. - * - * @see StringBuffer - * @see StringBuilder - * @see Charset - * @since 1.0 - */ -public final class String implements Serializable, Comparable<String>, CharSequence { - - private static final long serialVersionUID = -6849794470754667710L; - - private static final char REPLACEMENT_CHAR = (char) 0xfffd; - - /** - * CaseInsensitiveComparator compares Strings ignoring the case of the - * characters. - */ - private static final class CaseInsensitiveComparator implements - Comparator<String>, Serializable { - private static final long serialVersionUID = 8575799808933029326L; - - /** - * Compare the two objects to determine the relative ordering. - * - * @param o1 - * an Object to compare - * @param o2 - * an Object to compare - * @return an int < 0 if object1 is less than object2, 0 if they are - * equal, and > 0 if object1 is greater - * - * @throws ClassCastException - * if objects are not the correct type - */ - public int compare(String o1, String o2) { - return o1.compareToIgnoreCase(o2); - } - } - - /** - * A comparator ignoring the case of the characters. - */ - public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator(); - - private static final char[] ASCII; - static { - ASCII = new char[128]; - for (int i = 0; i < ASCII.length; ++i) { - ASCII[i] = (char) i; - } - } - - private final char[] value; - - private final int offset; - - private final int count; - - private int hashCode; - - /** - * Creates an empty string. - */ - public String() { - value = EmptyArray.CHAR; - offset = 0; - count = 0; - } - - /* - * Private constructor used for JIT optimization. - */ - @SuppressWarnings("unused") - private String(String s, char c) { - offset = 0; - value = new char[s.count + 1]; - count = s.count + 1; - System.arraycopy(s.value, s.offset, value, 0, s.count); - value[s.count] = c; - } - - /** - * Converts the byte array to a string using the system's - * {@link java.nio.charset.Charset#defaultCharset default charset}. - */ - @FindBugsSuppressWarnings("DM_DEFAULT_ENCODING") - public String(byte[] data) { - this(data, 0, data.length); - } - - /** - * Converts the byte array to a string, setting the high byte of every - * character to the specified value. - * - * @param data - * the byte array to convert to a string. - * @param high - * the high byte to use. - * @throws NullPointerException - * if {@code data == null}. - * @deprecated Use {@link #String(byte[])} or {@link #String(byte[], String)} instead. - */ - @Deprecated - public String(byte[] data, int high) { - this(data, high, 0, data.length); - } - - /** - * Converts a subsequence of the byte array to a string using the system's - * {@link java.nio.charset.Charset#defaultCharset default charset}. - * - * @throws NullPointerException - * if {@code data == null}. - * @throws IndexOutOfBoundsException - * if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length}. - */ - public String(byte[] data, int offset, int byteCount) { - this(data, offset, byteCount, Charset.defaultCharset()); - } - - /** - * Converts the byte array to a string, setting the high byte of every - * character to {@code high}. - * - * @throws NullPointerException - * if {@code data == null}. - * @throws IndexOutOfBoundsException - * if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length} - * - * @deprecated Use {@link #String(byte[], int, int)} instead. - */ - @Deprecated - public String(byte[] data, int high, int offset, int byteCount) { - if ((offset | byteCount) < 0 || byteCount > data.length - offset) { - throw failedBoundsCheck(data.length, offset, byteCount); - } - this.offset = 0; - this.value = new char[byteCount]; - this.count = byteCount; - high <<= 8; - for (int i = 0; i < count; i++) { - value[i] = (char) (high + (data[offset++] & 0xff)); - } - } - - /** - * Converts the byte array to a string using the named charset. - * - * <p>The behavior when the bytes cannot be decoded by the named charset - * is unspecified. Use {@link java.nio.charset.CharsetDecoder} for more control. - * - * @throws NullPointerException - * if {@code data == null}. - * @throws IndexOutOfBoundsException - * if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length}. - * @throws UnsupportedEncodingException - * if the named charset is not supported. - */ - public String(byte[] data, int offset, int byteCount, String charsetName) throws UnsupportedEncodingException { - this(data, offset, byteCount, Charset.forNameUEE(charsetName)); - } - - /** - * Converts the byte array to a string using the named charset. - * - * <p>The behavior when the bytes cannot be decoded by the named charset - * is unspecified. Use {@link java.nio.charset.CharsetDecoder} for more control. - * - * @throws NullPointerException - * if {@code data == null}. - * @throws UnsupportedEncodingException - * if {@code charsetName} is not supported. - */ - public String(byte[] data, String charsetName) throws UnsupportedEncodingException { - this(data, 0, data.length, Charset.forNameUEE(charsetName)); - } - - /** - * Converts the byte array to a string using the given charset. - * - * <p>The behavior when the bytes cannot be decoded by the given charset - * is to replace malformed input and unmappable characters with the charset's default - * replacement string. Use {@link java.nio.charset.CharsetDecoder} for more control. - * - * @throws IndexOutOfBoundsException - * if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length} - * @throws NullPointerException - * if {@code data == null} - * - * @since 1.6 - */ - public String(byte[] data, int offset, int byteCount, Charset charset) { - if ((offset | byteCount) < 0 || byteCount > data.length - offset) { - throw failedBoundsCheck(data.length, offset, byteCount); - } - - // We inline UTF-8, ISO-8859-1, and US-ASCII decoders for speed and because 'count' and - // 'value' are final. - String canonicalCharsetName = charset.name(); - if (canonicalCharsetName.equals("UTF-8")) { - byte[] d = data; - char[] v = new char[byteCount]; - - int idx = offset; - int last = offset + byteCount; - int s = 0; -outer: - while (idx < last) { - byte b0 = d[idx++]; - if ((b0 & 0x80) == 0) { - // 0xxxxxxx - // Range: U-00000000 - U-0000007F - int val = b0 & 0xff; - v[s++] = (char) val; - } else if (((b0 & 0xe0) == 0xc0) || ((b0 & 0xf0) == 0xe0) || - ((b0 & 0xf8) == 0xf0) || ((b0 & 0xfc) == 0xf8) || ((b0 & 0xfe) == 0xfc)) { - int utfCount = 1; - if ((b0 & 0xf0) == 0xe0) utfCount = 2; - else if ((b0 & 0xf8) == 0xf0) utfCount = 3; - else if ((b0 & 0xfc) == 0xf8) utfCount = 4; - else if ((b0 & 0xfe) == 0xfc) utfCount = 5; - - // 110xxxxx (10xxxxxx)+ - // Range: U-00000080 - U-000007FF (count == 1) - // Range: U-00000800 - U-0000FFFF (count == 2) - // Range: U-00010000 - U-001FFFFF (count == 3) - // Range: U-00200000 - U-03FFFFFF (count == 4) - // Range: U-04000000 - U-7FFFFFFF (count == 5) - - if (idx + utfCount > last) { - v[s++] = REPLACEMENT_CHAR; - continue; - } - - // Extract usable bits from b0 - int val = b0 & (0x1f >> (utfCount - 1)); - for (int i = 0; i < utfCount; ++i) { - byte b = d[idx++]; - if ((b & 0xc0) != 0x80) { - v[s++] = REPLACEMENT_CHAR; - idx--; // Put the input char back - continue outer; - } - // Push new bits in from the right side - val <<= 6; - val |= b & 0x3f; - } - - // Note: Java allows overlong char - // specifications To disallow, check that val - // is greater than or equal to the minimum - // value for each count: - // - // count min value - // ----- ---------- - // 1 0x80 - // 2 0x800 - // 3 0x10000 - // 4 0x200000 - // 5 0x4000000 - - // Allow surrogate values (0xD800 - 0xDFFF) to - // be specified using 3-byte UTF values only - if ((utfCount != 2) && (val >= 0xD800) && (val <= 0xDFFF)) { - v[s++] = REPLACEMENT_CHAR; - continue; - } - - // Reject chars greater than the Unicode maximum of U+10FFFF. - if (val > 0x10FFFF) { - v[s++] = REPLACEMENT_CHAR; - continue; - } - - // Encode chars from U+10000 up as surrogate pairs - if (val < 0x10000) { - v[s++] = (char) val; - } else { - int x = val & 0xffff; - int u = (val >> 16) & 0x1f; - int w = (u - 1) & 0xffff; - int hi = 0xd800 | (w << 6) | (x >> 10); - int lo = 0xdc00 | (x & 0x3ff); - v[s++] = (char) hi; - v[s++] = (char) lo; - } - } else { - // Illegal values 0x8*, 0x9*, 0xa*, 0xb*, 0xfd-0xff - v[s++] = REPLACEMENT_CHAR; - } - } - - if (s == byteCount) { - // We guessed right, so we can use our temporary array as-is. - this.offset = 0; - this.value = v; - this.count = s; - } else { - // Our temporary array was too big, so reallocate and copy. - this.offset = 0; - this.value = new char[s]; - this.count = s; - System.arraycopy(v, 0, value, 0, s); - } - } else if (canonicalCharsetName.equals("ISO-8859-1")) { - this.offset = 0; - this.value = new char[byteCount]; - this.count = byteCount; - Charsets.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); - } else { - CharBuffer cb = charset.decode(ByteBuffer.wrap(data, offset, byteCount)); - this.offset = 0; - this.count = cb.length(); - if (count > 0) { - // We could use cb.array() directly, but that would mean we'd have to trust - // the CharsetDecoder doesn't hang on to the CharBuffer and mutate it later, - // which would break String's immutability guarantee. It would also tend to - // mean that we'd be wasting memory because CharsetDecoder doesn't trim the - // array. So we copy. - this.value = new char[count]; - System.arraycopy(cb.array(), 0, value, 0, count); - } else { - this.value = EmptyArray.CHAR; - } - } - } - - /** - * Converts the byte array to a String using the given charset. - * - * @throws NullPointerException if {@code data == null} - * @since 1.6 - */ - public String(byte[] data, Charset charset) { - this(data, 0, data.length, charset); - } - - /** - * Initializes this string to contain the characters in the specified - * character array. Modifying the character array after creating the string - * has no effect on the string. - * - * @throws NullPointerException if {@code data == null} - */ - public String(char[] data) { - this(data, 0, data.length); - } - - /** - * Initializes this string to contain the specified characters in the - * character array. Modifying the character array after creating the string - * has no effect on the string. - * - * @throws NullPointerException - * if {@code data == null}. - * @throws IndexOutOfBoundsException - * if {@code charCount < 0 || offset < 0 || offset + charCount > data.length} - */ - public String(char[] data, int offset, int charCount) { - if ((offset | charCount) < 0 || charCount > data.length - offset) { - throw failedBoundsCheck(data.length, offset, charCount); - } - this.offset = 0; - this.value = new char[charCount]; - this.count = charCount; - System.arraycopy(data, offset, value, 0, count); - } - - /* - * Internal version of the String(char[], int, int) constructor. - * Does not range check, null check, or copy the character array. - */ - String(int offset, int charCount, char[] chars) { - this.value = chars; - this.offset = offset; - this.count = charCount; - } - - /** - * Constructs a new string with the same sequence of characters as {@code - * toCopy}. The returned string's <a href="#backing_array">backing array</a> - * is no larger than necessary. - */ - public String(String toCopy) { - value = (toCopy.value.length == toCopy.count) - ? toCopy.value - : Arrays.copyOfRange(toCopy.value, toCopy.offset, toCopy.offset + toCopy.length()); - offset = 0; - count = value.length; - } - - /* - * Private constructor useful for JIT optimization. - */ - @SuppressWarnings( { "unused", "nls" }) - private String(String s1, String s2) { - if (s1 == null) { - s1 = "null"; - } - if (s2 == null) { - s2 = "null"; - } - count = s1.count + s2.count; - value = new char[count]; - offset = 0; - System.arraycopy(s1.value, s1.offset, value, 0, s1.count); - System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count); - } - - /* - * Private constructor useful for JIT optimization. - */ - @SuppressWarnings( { "unused", "nls" }) - private String(String s1, String s2, String s3) { - if (s1 == null) { - s1 = "null"; - } - if (s2 == null) { - s2 = "null"; - } - if (s3 == null) { - s3 = "null"; - } - count = s1.count + s2.count + s3.count; - value = new char[count]; - offset = 0; - System.arraycopy(s1.value, s1.offset, value, 0, s1.count); - System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count); - System.arraycopy(s3.value, s3.offset, value, s1.count + s2.count, s3.count); - } - - /** - * Creates a {@code String} from the contents of the specified - * {@code StringBuffer}. - */ - public String(StringBuffer stringBuffer) { - offset = 0; - synchronized (stringBuffer) { - value = stringBuffer.shareValue(); - count = stringBuffer.length(); - } - } - - /** - * Creates a {@code String} from the sub-array of Unicode code points. - * - * @throws NullPointerException - * if {@code codePoints == null}. - * @throws IllegalArgumentException - * if any of the elements of {@code codePoints} are not valid - * Unicode code points. - * @throws IndexOutOfBoundsException - * if {@code offset} or {@code count} are not within the bounds - * of {@code codePoints}. - * @since 1.5 - */ - public String(int[] codePoints, int offset, int count) { - if (codePoints == null) { - throw new NullPointerException("codePoints == null"); - } - if ((offset | count) < 0 || count > codePoints.length - offset) { - throw failedBoundsCheck(codePoints.length, offset, count); - } - this.offset = 0; - this.value = new char[count * 2]; - int end = offset + count; - int c = 0; - for (int i = offset; i < end; i++) { - c += Character.toChars(codePoints[i], this.value, c); - } - this.count = c; - } - - /** - * Creates a {@code String} from the contents of the specified {@code - * StringBuilder}. - * - * @throws NullPointerException - * if {@code stringBuilder == null}. - * @since 1.5 - */ - public String(StringBuilder stringBuilder) { - if (stringBuilder == null) { - throw new NullPointerException("stringBuilder == null"); - } - this.offset = 0; - this.count = stringBuilder.length(); - this.value = new char[this.count]; - stringBuilder.getChars(0, this.count, this.value, 0); - } - - /* - * Creates a {@code String} that is s1 + v1. May be used by JIT code. - */ - @SuppressWarnings("unused") - private String(String s1, int v1) { - if (s1 == null) { - s1 = "null"; - } - String s2 = String.valueOf(v1); - int len = s1.count + s2.count; - value = new char[len]; - offset = 0; - System.arraycopy(s1.value, s1.offset, value, 0, s1.count); - System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count); - count = len; - } - - /** - * Returns the character at {@code index}. - * @throws IndexOutOfBoundsException if {@code index < 0} or {@code index >= length()}. - */ - public char charAt(int index) { - if (index < 0 || index >= count) { - throw indexAndLength(index); - } - return value[offset + index]; - } - - private StringIndexOutOfBoundsException indexAndLength(int index) { - throw new StringIndexOutOfBoundsException(this, index); - } - - private StringIndexOutOfBoundsException startEndAndLength(int start, int end) { - throw new StringIndexOutOfBoundsException(this, start, end - start); - } - - private StringIndexOutOfBoundsException failedBoundsCheck(int arrayLength, int offset, int count) { - throw new StringIndexOutOfBoundsException(arrayLength, offset, count); - } - - /** - * This isn't equivalent to either of ICU's u_foldCase case folds, and thus any of the Unicode - * case folds, but it's what the RI uses. - */ - private char foldCase(char ch) { - if (ch < 128) { - if ('A' <= ch && ch <= 'Z') { - return (char) (ch + ('a' - 'A')); - } - return ch; - } - return Character.toLowerCase(Character.toUpperCase(ch)); - } - - /** - * Compares the specified string to this string using the Unicode values of - * the characters. Returns 0 if the strings contain the same characters in - * the same order. Returns a negative integer if the first non-equal - * character in this string has a Unicode value which is less than the - * Unicode value of the character at the same position in the specified - * string, or if this string is a prefix of the specified string. Returns a - * positive integer if the first non-equal character in this string has a - * Unicode value which is greater than the Unicode value of the character at - * the same position in the specified string, or if the specified string is - * a prefix of this string. - * - * @param string - * the string to compare. - * @return 0 if the strings are equal, a negative integer if this string is - * before the specified string, or a positive integer if this string - * is after the specified string. - * @throws NullPointerException - * if {@code string} is {@code null}. - */ - public native int compareTo(String string); - - /** - * Compares the specified string to this string using the Unicode values of - * the characters, ignoring case differences. Returns 0 if the strings - * contain the same characters in the same order. Returns a negative integer - * if the first non-equal character in this string has a Unicode value which - * is less than the Unicode value of the character at the same position in - * the specified string, or if this string is a prefix of the specified - * string. Returns a positive integer if the first non-equal character in - * this string has a Unicode value which is greater than the Unicode value - * of the character at the same position in the specified string, or if the - * specified string is a prefix of this string. - * - * @param string - * the string to compare. - * @return 0 if the strings are equal, a negative integer if this string is - * before the specified string, or a positive integer if this string - * is after the specified string. - * @throws NullPointerException - * if {@code string} is {@code null}. - */ - public int compareToIgnoreCase(String string) { - int o1 = offset, o2 = string.offset, result; - int end = offset + (count < string.count ? count : string.count); - char c1, c2; - char[] target = string.value; - while (o1 < end) { - if ((c1 = value[o1++]) == (c2 = target[o2++])) { - continue; - } - c1 = foldCase(c1); - c2 = foldCase(c2); - if ((result = c1 - c2) != 0) { - return result; - } - } - return count - string.count; - } - - /** - * Concatenates this string and the specified string. - * - * @param string - * the string to concatenate - * @return a new string which is the concatenation of this string and the - * specified string. - */ - public String concat(String string) { - if (string.count > 0 && count > 0) { - char[] buffer = new char[count + string.count]; - System.arraycopy(value, offset, buffer, 0, count); - System.arraycopy(string.value, string.offset, buffer, count, string.count); - return new String(0, buffer.length, buffer); - } - return count == 0 ? string : this; - } - - /** - * Creates a new string containing the characters in the specified character - * array. Modifying the character array after creating the string has no - * effect on the string. - * - * @param data - * the array of characters. - * @return the new string. - * @throws NullPointerException - * if {@code data} is {@code null}. - */ - public static String copyValueOf(char[] data) { - return new String(data, 0, data.length); - } - - /** - * Creates a new string containing the specified characters in the character - * array. Modifying the character array after creating the string has no - * effect on the string. - * - * @param data - * the array of characters. - * @param start - * the starting offset in the character array. - * @param length - * the number of characters to use. - * @return the new string. - * @throws NullPointerException - * if {@code data} is {@code null}. - * @throws IndexOutOfBoundsException - * if {@code length < 0, start < 0} or {@code start + length > - * data.length}. - */ - public static String copyValueOf(char[] data, int start, int length) { - return new String(data, start, length); - } - - /** - * Compares the specified string to this string to determine if the - * specified string is a suffix. - * - * @param suffix - * the suffix to look for. - * @return {@code true} if the specified string is a suffix of this string, - * {@code false} otherwise. - * @throws NullPointerException - * if {@code suffix} is {@code null}. - */ - public boolean endsWith(String suffix) { - return regionMatches(count - suffix.count, suffix, 0, suffix.count); - } - - /** - * Compares the specified object to this string and returns true if they are - * equal. The object must be an instance of string with the same characters - * in the same order. - * - * @param other - * the object to compare. - * @return {@code true} if the specified object is equal to this string, - * {@code false} otherwise. - * @see #hashCode - */ - @Override public boolean equals(Object other) { - if (other == this) { - return true; - } - if (other instanceof String) { - String s = (String)other; - int count = this.count; - if (s.count != count) { - return false; - } - // TODO: we want to avoid many boundchecks in the loop below - // for long Strings until we have array equality intrinsic. - // Bad benchmarks just push .equals without first getting a - // hashCode hit (unlike real world use in a Hashtable). Filter - // out these long strings here. When we get the array equality - // intrinsic then remove this use of hashCode. - if (hashCode() != s.hashCode()) { - return false; - } - char[] value1 = value; - int offset1 = offset; - char[] value2 = s.value; - int offset2 = s.offset; - for (int end = offset1 + count; offset1 < end; ) { - if (value1[offset1] != value2[offset2]) { - return false; - } - offset1++; - offset2++; - } - return true; - } else { - return false; - } - } - - /** - * Compares the specified string to this string ignoring the case of the - * characters and returns true if they are equal. - * - * @param string - * the string to compare. - * @return {@code true} if the specified string is equal to this string, - * {@code false} otherwise. - */ - @FindBugsSuppressWarnings("ES_COMPARING_PARAMETER_STRING_WITH_EQ") - public boolean equalsIgnoreCase(String string) { - if (string == this) { - return true; - } - if (string == null || count != string.count) { - return false; - } - int o1 = offset, o2 = string.offset; - int end = offset + count; - char[] target = string.value; - while (o1 < end) { - char c1 = value[o1++]; - char c2 = target[o2++]; - if (c1 != c2 && foldCase(c1) != foldCase(c2)) { - return false; - } - } - return true; - } - - /** - * Mangles this string into a byte array by stripping the high order bits from - * each character. Use {@link #getBytes()} or {@link #getBytes(String)} instead. - * - * @param start - * the starting offset of characters to copy. - * @param end - * the ending offset of characters to copy. - * @param data - * the destination byte array. - * @param index - * the starting offset in the destination byte array. - * @throws NullPointerException - * if {@code data} is {@code null}. - * @throws IndexOutOfBoundsException - * if {@code start < 0}, {@code end > length()}, {@code index < - * 0} or {@code end - start > data.length - index}. - * @deprecated Use {@link #getBytes()} or {@link #getBytes(String)} instead. - */ - @Deprecated - public void getBytes(int start, int end, byte[] data, int index) { - // Note: last character not copied! - if (start >= 0 && start <= end && end <= count) { - end += offset; - try { - for (int i = offset + start; i < end; i++) { - data[index++] = (byte) value[i]; - } - } catch (ArrayIndexOutOfBoundsException ignored) { - throw failedBoundsCheck(data.length, index, end - start); - } - } else { - throw startEndAndLength(start, end); - } - } - - /** - * Returns a new byte array containing the characters of this string encoded using the - * system's {@link java.nio.charset.Charset#defaultCharset default charset}. - * - * <p>The behavior when this string cannot be represented in the system's default charset - * is unspecified. In practice, when the default charset is UTF-8 (as it is on Android), - * all strings can be encoded. - */ - public byte[] getBytes() { - return getBytes(Charset.defaultCharset()); - } - - /** - * Returns a new byte array containing the characters of this string encoded using the - * named charset. - * - * <p>The behavior when this string cannot be represented in the named charset - * is unspecified. Use {@link java.nio.charset.CharsetEncoder} for more control. - * - * @throws UnsupportedEncodingException if the charset is not supported - */ - public byte[] getBytes(String charsetName) throws UnsupportedEncodingException { - return getBytes(Charset.forNameUEE(charsetName)); - } - - /** - * Returns a new byte array containing the characters of this string encoded using the - * given charset. - * - * <p>The behavior when this string cannot be represented in the given charset - * is to replace malformed input and unmappable characters with the charset's default - * replacement byte array. Use {@link java.nio.charset.CharsetEncoder} for more control. - * - * @since 1.6 - */ - public byte[] getBytes(Charset charset) { - String canonicalCharsetName = charset.name(); - if (canonicalCharsetName.equals("UTF-8")) { - return Charsets.toUtf8Bytes(value, offset, count); - } else if (canonicalCharsetName.equals("ISO-8859-1")) { - return Charsets.toIsoLatin1Bytes(value, offset, count); - } else if (canonicalCharsetName.equals("US-ASCII")) { - return Charsets.toAsciiBytes(value, offset, count); - } else if (canonicalCharsetName.equals("UTF-16BE")) { - return Charsets.toBigEndianUtf16Bytes(value, offset, count); - } else { - CharBuffer chars = CharBuffer.wrap(this.value, this.offset, this.count); - ByteBuffer buffer = charset.encode(chars.asReadOnlyBuffer()); - byte[] bytes = new byte[buffer.limit()]; - buffer.get(bytes); - return bytes; - } - } - - /** - * Copies the specified characters in this string to the character array - * starting at the specified offset in the character array. - * - * @param start - * the starting offset of characters to copy. - * @param end - * the ending offset of characters to copy. - * @param buffer - * the destination character array. - * @param index - * the starting offset in the character array. - * @throws NullPointerException - * if {@code buffer} is {@code null}. - * @throws IndexOutOfBoundsException - * if {@code start < 0}, {@code end > length()}, {@code start > - * end}, {@code index < 0}, {@code end - start > buffer.length - - * index} - */ - public void getChars(int start, int end, char[] buffer, int index) { - // Note: last character not copied! - if (start >= 0 && start <= end && end <= count) { - System.arraycopy(value, start + offset, buffer, index, end - start); - } else { - // We throw StringIndexOutOfBoundsException rather than System.arraycopy's AIOOBE. - throw startEndAndLength(start, end); - } - } - - /** - * Version of getChars without bounds checks, for use by other classes - * within the java.lang package only. The caller is responsible for - * ensuring that start >= 0 && start <= end && end <= count. - */ - void _getChars(int start, int end, char[] buffer, int index) { - // NOTE last character not copied! - System.arraycopy(value, start + offset, buffer, index, end - start); - } - - @Override public int hashCode() { - int hash = hashCode; - if (hash == 0) { - if (count == 0) { - return 0; - } - final int end = count + offset; - final char[] chars = value; - for (int i = offset; i < end; ++i) { - hash = 31*hash + chars[i]; - } - hashCode = hash; - } - return hash; - } - - /** - * Searches in this string for the first index of the specified character. - * The search for the character starts at the beginning and moves towards - * the end of this string. - * - * @param c - * the character to find. - * @return the index in this string of the specified character, -1 if the - * character isn't found. - */ - public int indexOf(int c) { - // TODO: just "return indexOf(c, 0);" when the JIT can inline that deep. - if (c > 0xffff) { - return indexOfSupplementary(c, 0); - } - return fastIndexOf(c, 0); - } - - /** - * Searches in this string for the index of the specified character. The - * search for the character starts at the specified offset and moves towards - * the end of this string. - * - * @param c - * the character to find. - * @param start - * the starting offset. - * @return the index in this string of the specified character, -1 if the - * character isn't found. - */ - public int indexOf(int c, int start) { - if (c > 0xffff) { - return indexOfSupplementary(c, start); - } - return fastIndexOf(c, start); - } - - private native int fastIndexOf(int c, int start); - - private int indexOfSupplementary(int c, int start) { - if (!Character.isSupplementaryCodePoint(c)) { - return -1; - } - char[] chars = Character.toChars(c); - String needle = new String(0, chars.length, chars); - return indexOf(needle, start); - } - - /** - * Searches in this string for the first index of the specified string. The - * search for the string starts at the beginning and moves towards the end - * of this string. - * - * @param string - * the string to find. - * @return the index of the first character of the specified string in this - * string, -1 if the specified string is not a substring. - * @throws NullPointerException - * if {@code string} is {@code null}. - */ - public int indexOf(String string) { - int start = 0; - int subCount = string.count; - int _count = count; - if (subCount > 0) { - if (subCount > _count) { - return -1; - } - char[] target = string.value; - int subOffset = string.offset; - char firstChar = target[subOffset]; - int end = subOffset + subCount; - while (true) { - int i = indexOf(firstChar, start); - if (i == -1 || subCount + i > _count) { - return -1; // handles subCount > count || start >= count - } - int o1 = offset + i, o2 = subOffset; - char[] _value = value; - while (++o2 < end && _value[++o1] == target[o2]) { - // Intentionally empty - } - if (o2 == end) { - return i; - } - start = i + 1; - } - } - return start < _count ? start : _count; - } - - /** - * Searches in this string for the index of the specified string. The search - * for the string starts at the specified offset and moves towards the end - * of this string. - * - * @param subString - * the string to find. - * @param start - * the starting offset. - * @return the index of the first character of the specified string in this - * string, -1 if the specified string is not a substring. - * @throws NullPointerException - * if {@code subString} is {@code null}. - */ - public int indexOf(String subString, int start) { - if (start < 0) { - start = 0; - } - int subCount = subString.count; - int _count = count; - if (subCount > 0) { - if (subCount + start > _count) { - return -1; - } - char[] target = subString.value; - int subOffset = subString.offset; - char firstChar = target[subOffset]; - int end = subOffset + subCount; - while (true) { - int i = indexOf(firstChar, start); - if (i == -1 || subCount + i > _count) { - return -1; // handles subCount > count || start >= count - } - int o1 = offset + i, o2 = subOffset; - char[] _value = value; - while (++o2 < end && _value[++o1] == target[o2]) { - // Intentionally empty - } - if (o2 == end) { - return i; - } - start = i + 1; - } - } - return start < _count ? start : _count; - } - - /** - * Returns an interned string equal to this string. The VM maintains an internal set of - * unique strings. All string literals found in loaded classes' - * constant pools are automatically interned. Manually-interned strings are only weakly - * referenced, so calling {@code intern} won't lead to unwanted retention. - * - * <p>Interning is typically used because it guarantees that for interned strings - * {@code a} and {@code b}, {@code a.equals(b)} can be simplified to - * {@code a == b}. (This is not true of non-interned strings.) - * - * <p>Many applications find it simpler and more convenient to use an explicit - * {@link java.util.HashMap} to implement their own pools. - */ - public native String intern(); - - /** - * Returns true if the length of this string is 0. - * - * @since 1.6 - */ - public boolean isEmpty() { - return count == 0; - } - - /** - * Returns the last index of the code point {@code c}, or -1. - * The search for the character starts at the end and moves towards the - * beginning of this string. - */ - public int lastIndexOf(int c) { - if (c > 0xffff) { - return lastIndexOfSupplementary(c, Integer.MAX_VALUE); - } - int _count = count; - int _offset = offset; - char[] _value = value; - for (int i = _offset + _count - 1; i >= _offset; --i) { - if (_value[i] == c) { - return i - _offset; - } - } - return -1; - } - - /** - * Returns the last index of the code point {@code c}, or -1. - * The search for the character starts at offset {@code start} and moves towards - * the beginning of this string. - */ - public int lastIndexOf(int c, int start) { - if (c > 0xffff) { - return lastIndexOfSupplementary(c, start); - } - int _count = count; - int _offset = offset; - char[] _value = value; - if (start >= 0) { - if (start >= _count) { - start = _count - 1; - } - for (int i = _offset + start; i >= _offset; --i) { - if (_value[i] == c) { - return i - _offset; - } - } - } - return -1; - } - - private int lastIndexOfSupplementary(int c, int start) { - if (!Character.isSupplementaryCodePoint(c)) { - return -1; - } - char[] chars = Character.toChars(c); - String needle = new String(0, chars.length, chars); - return lastIndexOf(needle, start); - } - - /** - * Searches in this string for the last index of the specified string. The - * search for the string starts at the end and moves towards the beginning - * of this string. - * - * @param string - * the string to find. - * @return the index of the first character of the specified string in this - * string, -1 if the specified string is not a substring. - * @throws NullPointerException - * if {@code string} is {@code null}. - */ - public int lastIndexOf(String string) { - // Use count instead of count - 1 so lastIndexOf("") returns count - return lastIndexOf(string, count); - } - - /** - * Searches in this string for the index of the specified string. The search - * for the string starts at the specified offset and moves towards the - * beginning of this string. - * - * @param subString - * the string to find. - * @param start - * the starting offset. - * @return the index of the first character of the specified string in this - * string , -1 if the specified string is not a substring. - * @throws NullPointerException - * if {@code subString} is {@code null}. - */ - public int lastIndexOf(String subString, int start) { - int subCount = subString.count; - if (subCount <= count && start >= 0) { - if (subCount > 0) { - if (start > count - subCount) { - start = count - subCount; - } - // count and subCount are both >= 1 - char[] target = subString.value; - int subOffset = subString.offset; - char firstChar = target[subOffset]; - int end = subOffset + subCount; - while (true) { - int i = lastIndexOf(firstChar, start); - if (i == -1) { - return -1; - } - int o1 = offset + i, o2 = subOffset; - while (++o2 < end && value[++o1] == target[o2]) { - // Intentionally empty - } - if (o2 == end) { - return i; - } - start = i - 1; - } - } - return start < count ? start : count; - } - return -1; - } - - /** - * Returns the number of characters in this string. - */ - public int length() { - return count; - } - - /** - * Compares the specified string to this string and compares the specified - * range of characters to determine if they are the same. - * - * @param thisStart - * the starting offset in this string. - * @param string - * the string to compare. - * @param start - * the starting offset in the specified string. - * @param length - * the number of characters to compare. - * @return {@code true} if the ranges of characters are equal, {@code false} - * otherwise - * @throws NullPointerException - * if {@code string} is {@code null}. - */ - public boolean regionMatches(int thisStart, String string, int start, int length) { - if (string == null) { - throw new NullPointerException("string == null"); - } - if (start < 0 || string.count - start < length) { - return false; - } - if (thisStart < 0 || count - thisStart < length) { - return false; - } - if (length <= 0) { - return true; - } - int o1 = offset + thisStart, o2 = string.offset + start; - char[] value1 = value; - char[] value2 = string.value; - for (int i = 0; i < length; ++i) { - if (value1[o1 + i] != value2[o2 + i]) { - return false; - } - } - return true; - } - - /** - * Compares the specified string to this string and compares the specified - * range of characters to determine if they are the same. When ignoreCase is - * true, the case of the characters is ignored during the comparison. - * - * @param ignoreCase - * specifies if case should be ignored. - * @param thisStart - * the starting offset in this string. - * @param string - * the string to compare. - * @param start - * the starting offset in the specified string. - * @param length - * the number of characters to compare. - * @return {@code true} if the ranges of characters are equal, {@code false} - * otherwise. - * @throws NullPointerException - * if {@code string} is {@code null}. - */ - public boolean regionMatches(boolean ignoreCase, int thisStart, String string, int start, int length) { - if (!ignoreCase) { - return regionMatches(thisStart, string, start, length); - } - if (string == null) { - throw new NullPointerException("string == null"); - } - if (thisStart < 0 || length > count - thisStart) { - return false; - } - if (start < 0 || length > string.count - start) { - return false; - } - thisStart += offset; - start += string.offset; - int end = thisStart + length; - char[] target = string.value; - while (thisStart < end) { - char c1 = value[thisStart++]; - char c2 = target[start++]; - if (c1 != c2 && foldCase(c1) != foldCase(c2)) { - return false; - } - } - return true; - } - - /** - * Copies this string replacing occurrences of the specified character with - * another character. - * - * @param oldChar - * the character to replace. - * @param newChar - * the replacement character. - * @return a new string with occurrences of oldChar replaced by newChar. - */ - public String replace(char oldChar, char newChar) { - char[] buffer = value; - int _offset = offset; - int _count = count; - - int idx = _offset; - int last = _offset + _count; - boolean copied = false; - while (idx < last) { - if (buffer[idx] == oldChar) { - if (!copied) { - char[] newBuffer = new char[_count]; - System.arraycopy(buffer, _offset, newBuffer, 0, _count); - buffer = newBuffer; - idx -= _offset; - last -= _offset; - copied = true; - } - buffer[idx] = newChar; - } - idx++; - } - - return copied ? new String(0, count, buffer) : this; - } - - /** - * Copies this string replacing occurrences of the specified target sequence - * with another sequence. The string is processed from the beginning to the - * end. - * - * @param target - * the sequence to replace. - * @param replacement - * the replacement sequence. - * @return the resulting string. - * @throws NullPointerException - * if {@code target} or {@code replacement} is {@code null}. - */ - public String replace(CharSequence target, CharSequence replacement) { - if (target == null) { - throw new NullPointerException("target == null"); - } - if (replacement == null) { - throw new NullPointerException("replacement == null"); - } - - String targetString = target.toString(); - int matchStart = indexOf(targetString, 0); - if (matchStart == -1) { - // If there's nothing to replace, return the original string untouched. - return this; - } - - String replacementString = replacement.toString(); - - // The empty target matches at the start and end and between each character. - int targetLength = targetString.length(); - if (targetLength == 0) { - // The result contains the original 'count' characters, a copy of the - // replacement string before every one of those characters, and a final - // copy of the replacement string at the end. - int resultLength = count + (count + 1) * replacementString.length(); - StringBuilder result = new StringBuilder(resultLength); - result.append(replacementString); - int end = offset + count; - for (int i = offset; i != end; ++i) { - result.append(value[i]); - result.append(replacementString); - } - return result.toString(); - } - - StringBuilder result = new StringBuilder(count); - int searchStart = 0; - do { - // Copy characters before the match... - result.append(value, offset + searchStart, matchStart - searchStart); - // Insert the replacement... - result.append(replacementString); - // And skip over the match... - searchStart = matchStart + targetLength; - } while ((matchStart = indexOf(targetString, searchStart)) != -1); - // Copy any trailing chars... - result.append(value, offset + searchStart, count - searchStart); - return result.toString(); - } - - /** - * Compares the specified string to this string to determine if the - * specified string is a prefix. - * - * @param prefix - * the string to look for. - * @return {@code true} if the specified string is a prefix of this string, - * {@code false} otherwise - * @throws NullPointerException - * if {@code prefix} is {@code null}. - */ - public boolean startsWith(String prefix) { - return startsWith(prefix, 0); - } - - /** - * Compares the specified string to this string, starting at the specified - * offset, to determine if the specified string is a prefix. - * - * @param prefix - * the string to look for. - * @param start - * the starting offset. - * @return {@code true} if the specified string occurs in this string at the - * specified offset, {@code false} otherwise. - * @throws NullPointerException - * if {@code prefix} is {@code null}. - */ - public boolean startsWith(String prefix, int start) { - return regionMatches(start, prefix, 0, prefix.count); - } - - /** - * Returns a string containing a suffix of this string. The returned string - * shares this string's <a href="#backing_array">backing array</a>. - * - * @param start - * the offset of the first character. - * @return a new string containing the characters from start to the end of - * the string. - * @throws IndexOutOfBoundsException - * if {@code start < 0} or {@code start > length()}. - */ - public String substring(int start) { - if (start == 0) { - return this; - } - if (start >= 0 && start <= count) { - return new String(offset + start, count - start, value); - } - throw indexAndLength(start); - } - - /** - * Returns a string containing a subsequence of characters from this string. - * The returned string shares this string's <a href="#backing_array">backing - * array</a>. - * - * @param start - * the offset of the first character. - * @param end - * the offset one past the last character. - * @return a new string containing the characters from start to end - 1 - * @throws IndexOutOfBoundsException - * if {@code start < 0}, {@code start > end} or {@code end > - * length()}. - */ - public String substring(int start, int end) { - if (start == 0 && end == count) { - return this; - } - // NOTE last character not copied! - // Fast range check. - if (start >= 0 && start <= end && end <= count) { - return new String(offset + start, end - start, value); - } - throw startEndAndLength(start, end); - } - - /** - * Returns a new {@code char} array containing a copy of the characters in this string. - * This is expensive and rarely useful. If you just want to iterate over the characters in - * the string, use {@link #charAt} instead. - */ - public char[] toCharArray() { - char[] buffer = new char[count]; - System.arraycopy(value, offset, buffer, 0, count); - return buffer; - } - - /** - * Converts this string to lower case, using the rules of the user's default locale. - * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>". - * - * @return a new lower case string, or {@code this} if it's already all lower case. - */ - public String toLowerCase() { - return CaseMapper.toLowerCase(Locale.getDefault(), this, value, offset, count); - } - - /** - * Converts this string to lower case, using the rules of {@code locale}. - * - * <p>Most case mappings are unaffected by the language of a {@code Locale}. Exceptions include - * dotted and dotless I in Azeri and Turkish locales, and dotted and dotless I and J in - * Lithuanian locales. On the other hand, it isn't necessary to provide a Greek locale to get - * correct case mapping of Greek characters: any locale will do. - * - * <p>See <a href="http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt">http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt</a> - * for full details of context- and language-specific special cases. - * - * @return a new lower case string, or {@code this} if it's already all lower case. - */ - public String toLowerCase(Locale locale) { - return CaseMapper.toLowerCase(locale, this, value, offset, count); - } - - /** - * Returns this string. - */ - @Override - public String toString() { - return this; - } - - /** - * Converts this this string to upper case, using the rules of the user's default locale. - * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>". - * - * @return a new upper case string, or {@code this} if it's already all upper case. - */ - public String toUpperCase() { - return CaseMapper.toUpperCase(Locale.getDefault(), this, value, offset, count); - } - - /** - * Converts this this string to upper case, using the rules of {@code locale}. - * - * <p>Most case mappings are unaffected by the language of a {@code Locale}. Exceptions include - * dotted and dotless I in Azeri and Turkish locales, and dotted and dotless I and J in - * Lithuanian locales. On the other hand, it isn't necessary to provide a Greek locale to get - * correct case mapping of Greek characters: any locale will do. - * - * <p>See <a href="http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt">http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt</a> - * for full details of context- and language-specific special cases. - * - * @return a new upper case string, or {@code this} if it's already all upper case. - */ - public String toUpperCase(Locale locale) { - return CaseMapper.toUpperCase(locale, this, value, offset, count); - } - - /** - * Copies this string removing white space characters from the beginning and - * end of the string. - * - * @return a new string with characters <code><= \\u0020</code> removed from - * the beginning and the end. - */ - public String trim() { - int start = offset, last = offset + count - 1; - int end = last; - while ((start <= end) && (value[start] <= ' ')) { - start++; - } - while ((end >= start) && (value[end] <= ' ')) { - end--; - } - if (start == offset && end == last) { - return this; - } - return new String(start, end - start + 1, value); - } - - /** - * Creates a new string containing the characters in the specified character - * array. Modifying the character array after creating the string has no - * effect on the string. - * - * @param data - * the array of characters. - * @return the new string. - * @throws NullPointerException - * if {@code data} is {@code null}. - */ - public static String valueOf(char[] data) { - return new String(data, 0, data.length); - } - - /** - * Creates a new string containing the specified characters in the character - * array. Modifying the character array after creating the string has no - * effect on the string. - * - * @param data - * the array of characters. - * @param start - * the starting offset in the character array. - * @param length - * the number of characters to use. - * @return the new string. - * @throws IndexOutOfBoundsException - * if {@code length < 0}, {@code start < 0} or {@code start + - * length > data.length} - * @throws NullPointerException - * if {@code data} is {@code null}. - */ - public static String valueOf(char[] data, int start, int length) { - return new String(data, start, length); - } - - /** - * Converts the specified character to its string representation. - * - * @param value - * the character. - * @return the character converted to a string. - */ - public static String valueOf(char value) { - String s; - if (value < 128) { - s = new String(value, 1, ASCII); - } else { - s = new String(0, 1, new char[] { value }); - } - s.hashCode = value; - return s; - } - - /** - * Converts the specified double to its string representation. - * - * @param value - * the double. - * @return the double converted to a string. - */ - public static String valueOf(double value) { - return Double.toString(value); - } - - /** - * Converts the specified float to its string representation. - * - * @param value - * the float. - * @return the float converted to a string. - */ - public static String valueOf(float value) { - return Float.toString(value); - } - - /** - * Converts the specified integer to its string representation. - * - * @param value - * the integer. - * @return the integer converted to a string. - */ - public static String valueOf(int value) { - return Integer.toString(value); - } - - /** - * Converts the specified long to its string representation. - * - * @param value - * the long. - * @return the long converted to a string. - */ - public static String valueOf(long value) { - return Long.toString(value); - } - - /** - * Converts the specified object to its string representation. If the object - * is null return the string {@code "null"}, otherwise use {@code - * toString()} to get the string representation. - * - * @param value - * the object. - * @return the object converted to a string, or the string {@code "null"}. - */ - public static String valueOf(Object value) { - return value != null ? value.toString() : "null"; - } - - /** - * Converts the specified boolean to its string representation. When the - * boolean is {@code true} return {@code "true"}, otherwise return {@code - * "false"}. - * - * @param value - * the boolean. - * @return the boolean converted to a string. - */ - public static String valueOf(boolean value) { - return value ? "true" : "false"; - } - - /** - * Returns whether the characters in the StringBuffer {@code strbuf} are the - * same as those in this string. - * - * @param strbuf - * the StringBuffer to compare this string to. - * @return {@code true} if the characters in {@code strbuf} are identical to - * those in this string. If they are not, {@code false} will be - * returned. - * @throws NullPointerException - * if {@code strbuf} is {@code null}. - * @since 1.4 - */ - public boolean contentEquals(StringBuffer strbuf) { - synchronized (strbuf) { - int size = strbuf.length(); - if (count != size) { - return false; - } - return regionMatches(0, new String(0, size, strbuf.getValue()), 0, - size); - } - } - - /** - * Compares a {@code CharSequence} to this {@code String} to determine if - * their contents are equal. - * - * @param cs - * the character sequence to compare to. - * @return {@code true} if equal, otherwise {@code false} - * @since 1.5 - */ - public boolean contentEquals(CharSequence cs) { - if (cs == null) { - throw new NullPointerException("cs == null"); - } - - int len = cs.length(); - - if (len != count) { - return false; - } - - if (len == 0 && count == 0) { - return true; // since both are empty strings - } - - return regionMatches(0, cs.toString(), 0, len); - } - - /** - * Tests whether this string matches the given {@code regularExpression}. This method returns - * true only if the regular expression matches the <i>entire</i> input string. A common mistake is - * to assume that this method behaves like {@link #contains}; if you want to match anywhere - * within the input string, you need to add {@code .*} to the beginning and end of your - * regular expression. See {@link Pattern#matches}. - * - * <p>If the same regular expression is to be used for multiple operations, it may be more - * efficient to reuse a compiled {@code Pattern}. - * - * @throws PatternSyntaxException - * if the syntax of the supplied regular expression is not - * valid. - * @throws NullPointerException if {@code regularExpression == null} - * @since 1.4 - */ - public boolean matches(String regularExpression) { - return Pattern.matches(regularExpression, this); - } - - /** - * Replaces all matches for {@code regularExpression} within this string with the given - * {@code replacement}. - * See {@link Pattern} for regular expression syntax. - * - * <p>If the same regular expression is to be used for multiple operations, it may be more - * efficient to reuse a compiled {@code Pattern}. - * - * @throws PatternSyntaxException - * if the syntax of the supplied regular expression is not - * valid. - * @throws NullPointerException if {@code regularExpression == null} - * @see Pattern - * @since 1.4 - */ - public String replaceAll(String regularExpression, String replacement) { - return Pattern.compile(regularExpression).matcher(this).replaceAll(replacement); - } - - /** - * Replaces the first match for {@code regularExpression} within this string with the given - * {@code replacement}. - * See {@link Pattern} for regular expression syntax. - * - * <p>If the same regular expression is to be used for multiple operations, it may be more - * efficient to reuse a compiled {@code Pattern}. - * - * @throws PatternSyntaxException - * if the syntax of the supplied regular expression is not - * valid. - * @throws NullPointerException if {@code regularExpression == null} - * @see Pattern - * @since 1.4 - */ - public String replaceFirst(String regularExpression, String replacement) { - return Pattern.compile(regularExpression).matcher(this).replaceFirst(replacement); - } - - /** - * Splits this string using the supplied {@code regularExpression}. - * Equivalent to {@code split(regularExpression, 0)}. - * See {@link Pattern#split(CharSequence, int)} for an explanation of {@code limit}. - * See {@link Pattern} for regular expression syntax. - * - * <p>If the same regular expression is to be used for multiple operations, it may be more - * efficient to reuse a compiled {@code Pattern}. - * - * @throws NullPointerException if {@code regularExpression == null} - * @throws PatternSyntaxException - * if the syntax of the supplied regular expression is not - * valid. - * @see Pattern - * @since 1.4 - */ - public String[] split(String regularExpression) { - return split(regularExpression, 0); - } - - /** - * Splits this string using the supplied {@code regularExpression}. - * See {@link Pattern#split(CharSequence, int)} for an explanation of {@code limit}. - * See {@link Pattern} for regular expression syntax. - * - * <p>If the same regular expression is to be used for multiple operations, it may be more - * efficient to reuse a compiled {@code Pattern}. - * - * @throws NullPointerException if {@code regularExpression == null} - * @throws PatternSyntaxException - * if the syntax of the supplied regular expression is not - * valid. - * @since 1.4 - */ - public String[] split(String regularExpression, int limit) { - String[] result = java.util.regex.Splitter.fastSplit(regularExpression, this, limit); - return result != null ? result : Pattern.compile(regularExpression).split(this, limit); - } - - /** - * Has the same result as the substring function, but is present so that - * string may implement the CharSequence interface. - * - * @param start - * the offset the first character. - * @param end - * the offset of one past the last character to include. - * @return the subsequence requested. - * @throws IndexOutOfBoundsException - * if {@code start < 0}, {@code end < 0}, {@code start > end} or - * {@code end > length()}. - * @see java.lang.CharSequence#subSequence(int, int) - * @since 1.4 - */ - public CharSequence subSequence(int start, int end) { - return substring(start, end); - } - - /** - * Returns the Unicode code point at the given {@code index}. - * - * @throws IndexOutOfBoundsException if {@code index < 0 || index >= length()} - * @see Character#codePointAt(char[], int, int) - * @since 1.5 - */ - public int codePointAt(int index) { - if (index < 0 || index >= count) { - throw indexAndLength(index); - } - return Character.codePointAt(value, offset + index, offset + count); - } - - /** - * Returns the Unicode code point that precedes the given {@code index}. - * - * @throws IndexOutOfBoundsException if {@code index < 1 || index > length()} - * @see Character#codePointBefore(char[], int, int) - * @since 1.5 - */ - public int codePointBefore(int index) { - if (index < 1 || index > count) { - throw indexAndLength(index); - } - return Character.codePointBefore(value, offset + index, offset); - } - - /** - * Calculates the number of Unicode code points between {@code start} - * and {@code end}. - * - * @param start - * the inclusive beginning index of the subsequence. - * @param end - * the exclusive end index of the subsequence. - * @return the number of Unicode code points in the subsequence. - * @throws IndexOutOfBoundsException - * if {@code start < 0 || end > length() || start > end} - * @see Character#codePointCount(CharSequence, int, int) - * @since 1.5 - */ - public int codePointCount(int start, int end) { - if (start < 0 || end > count || start > end) { - throw startEndAndLength(start, end); - } - return Character.codePointCount(value, offset + start, end - start); - } - - /** - * Determines if this {@code String} contains the sequence of characters in - * the {@code CharSequence} passed. - * - * @param cs - * the character sequence to search for. - * @return {@code true} if the sequence of characters are contained in this - * string, otherwise {@code false}. - * @since 1.5 - */ - public boolean contains(CharSequence cs) { - if (cs == null) { - throw new NullPointerException("cs == null"); - } - return indexOf(cs.toString()) >= 0; - } - - /** - * Returns the index within this object that is offset from {@code index} by - * {@code codePointOffset} code points. - * - * @param index - * the index within this object to calculate the offset from. - * @param codePointOffset - * the number of code points to count. - * @return the index within this object that is the offset. - * @throws IndexOutOfBoundsException - * if {@code index} is negative or greater than {@code length()} - * or if there aren't enough code points before or after {@code - * index} to match {@code codePointOffset}. - * @since 1.5 - */ - public int offsetByCodePoints(int index, int codePointOffset) { - int s = index + offset; - int r = Character.offsetByCodePoints(value, offset, count, s, codePointOffset); - return r - offset; - } - - /** - * Returns a localized formatted string, using the supplied format and arguments, - * using the user's default locale. - * - * <p>If you're formatting a string other than for human - * consumption, you should use the {@code format(Locale, String, Object...)} - * overload and supply {@code Locale.US}. See - * "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>". - * - * @param format the format string (see {@link java.util.Formatter#format}) - * @param args - * the list of arguments passed to the formatter. If there are - * more arguments than required by {@code format}, - * additional arguments are ignored. - * @return the formatted string. - * @throws NullPointerException if {@code format == null} - * @throws java.util.IllegalFormatException - * if the format is invalid. - * @since 1.5 - */ - public static String format(String format, Object... args) { - return format(Locale.getDefault(), format, args); - } - - /** - * Returns a formatted string, using the supplied format and arguments, - * localized to the given locale. - * - * @param locale - * the locale to apply; {@code null} value means no localization. - * @param format the format string (see {@link java.util.Formatter#format}) - * @param args - * the list of arguments passed to the formatter. If there are - * more arguments than required by {@code format}, - * additional arguments are ignored. - * @return the formatted string. - * @throws NullPointerException if {@code format == null} - * @throws java.util.IllegalFormatException - * if the format is invalid. - * @since 1.5 - */ - public static String format(Locale locale, String format, Object... args) { - if (format == null) { - throw new NullPointerException("format == null"); - } - int bufferSize = format.length() + (args == null ? 0 : args.length * 10); - Formatter f = new Formatter(new StringBuilder(bufferSize), locale); - return f.format(format, args).toString(); - } - - /* - * An implementation of a String.indexOf that is supposed to perform - * substantially better than the default algorithm if the "needle" (the - * subString being searched for) is a constant string. - * - * For example, a JIT, upon encountering a call to String.indexOf(String), - * where the needle is a constant string, may compute the values cache, md2 - * and lastChar, and change the call to the following method. - */ - @FindBugsSuppressWarnings("UPM_UNCALLED_PRIVATE_METHOD") - @SuppressWarnings("unused") - private static int indexOf(String haystackString, String needleString, - int cache, int md2, char lastChar) { - char[] haystack = haystackString.value; - int haystackOffset = haystackString.offset; - int haystackLength = haystackString.count; - char[] needle = needleString.value; - int needleOffset = needleString.offset; - int needleLength = needleString.count; - int needleLengthMinus1 = needleLength - 1; - int haystackEnd = haystackOffset + haystackLength; - outer_loop: for (int i = haystackOffset + needleLengthMinus1; i < haystackEnd;) { - if (lastChar == haystack[i]) { - for (int j = 0; j < needleLengthMinus1; ++j) { - if (needle[j + needleOffset] != haystack[i + j - - needleLengthMinus1]) { - int skip = 1; - if ((cache & (1 << haystack[i])) == 0) { - skip += j; - } - i += Math.max(md2, skip); - continue outer_loop; - } - } - return i - needleLengthMinus1 - haystackOffset; - } - - if ((cache & (1 << haystack[i])) == 0) { - i += needleLengthMinus1; - } - i++; - } - return -1; - } -} diff --git a/libdvm/src/main/java/java/lang/Thread.java b/libdvm/src/main/java/java/lang/Thread.java deleted file mode 100644 index a40dde1..0000000 --- a/libdvm/src/main/java/java/lang/Thread.java +++ /dev/null @@ -1,1288 +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; - -import dalvik.system.VMStack; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import libcore.util.EmptyArray; - -/** - * A {@code Thread} is a concurrent unit of execution. It has its own call stack - * for methods being invoked, their arguments and local variables. Each application - * has at least one thread running when it is started, the main thread, in the main - * {@link ThreadGroup}. The runtime keeps its own threads in the system thread - * group. - * - * <p>There are two ways to execute code in a new thread. - * You can either subclass {@code Thread} and overriding its {@link #run()} method, - * or construct a new {@code Thread} and pass a {@link Runnable} to the constructor. - * In either case, the {@link #start()} method must be called to actually execute - * the new {@code Thread}. - * - * <p>Each {@code Thread} has an integer priority that affect how the thread is - * scheduled by the OS. A new thread inherits the priority of its parent. - * A thread's priority can be set using the {@link #setPriority(int)} method. - */ -public class Thread implements Runnable { - private static final int NANOS_PER_MILLI = 1000000; - - /** Park states */ - private static class ParkState { - /** park state indicating unparked */ - private static final int UNPARKED = 1; - - /** park state indicating preemptively unparked */ - private static final int PREEMPTIVELY_UNPARKED = 2; - - /** park state indicating parked */ - private static final int PARKED = 3; - } - - /** - * A representation of a thread's state. A given thread may only be in one - * state at a time. - */ - public enum State { - /** - * The thread has been created, but has never been started. - */ - NEW, - /** - * The thread may be run. - */ - RUNNABLE, - /** - * The thread is blocked and waiting for a lock. - */ - BLOCKED, - /** - * The thread is waiting. - */ - WAITING, - /** - * The thread is waiting for a specified amount of time. - */ - TIMED_WAITING, - /** - * The thread has been terminated. - */ - TERMINATED - } - - /** - * The maximum priority value allowed for a thread. - * This corresponds to (but does not have the same value as) - * {@code android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY}. - */ - public static final int MAX_PRIORITY = 10; - - /** - * The minimum priority value allowed for a thread. - * This corresponds to (but does not have the same value as) - * {@code android.os.Process.THREAD_PRIORITY_LOWEST}. - */ - public static final int MIN_PRIORITY = 1; - - /** - * The normal (default) priority value assigned to the main thread. - * This corresponds to (but does not have the same value as) - * {@code android.os.Process.THREAD_PRIORITY_DEFAULT}. - - */ - public static final int NORM_PRIORITY = 5; - - /* some of these are accessed directly by the VM; do not rename them */ - volatile VMThread vmThread; - volatile ThreadGroup group; - volatile boolean daemon; - volatile String name; - volatile int priority; - volatile long stackSize; - Runnable target; - private static int count = 0; - - /** - * Holds the thread's ID. We simply count upwards, so - * each Thread has a unique ID. - */ - private long id; - - /** - * Normal thread local values. - */ - ThreadLocal.Values localValues; - - /** - * Inheritable thread local values. - */ - ThreadLocal.Values inheritableValues; - - /** Callbacks to run on interruption. */ - private final List<Runnable> interruptActions = new ArrayList<Runnable>(); - - /** - * Holds the class loader for this Thread, in case there is one. - */ - private ClassLoader contextClassLoader; - - /** - * Holds the handler for uncaught exceptions in this Thread, - * in case there is one. - */ - private UncaughtExceptionHandler uncaughtHandler; - - /** - * Holds the default handler for uncaught exceptions, in case there is one. - */ - private static UncaughtExceptionHandler defaultUncaughtHandler; - - /** - * Reflects whether this Thread has already been started. A Thread - * can only be started once (no recycling). Also, we need it to deduce - * the proper Thread status. - */ - boolean hasBeenStarted = false; - - /** the park state of the thread */ - private int parkState = ParkState.UNPARKED; - - /** The synchronization object responsible for this thread parking. */ - private Object parkBlocker; - - /** - * Constructs a new {@code Thread} with no {@code Runnable} object and a - * newly generated name. The new {@code Thread} will belong to the same - * {@code ThreadGroup} as the {@code Thread} calling this constructor. - * - * @see java.lang.ThreadGroup - * @see java.lang.Runnable - */ - public Thread() { - create(null, null, null, 0); - } - - /** - * Constructs a new {@code Thread} with a {@code Runnable} object and a - * newly generated name. The new {@code Thread} will belong to the same - * {@code ThreadGroup} as the {@code Thread} calling this constructor. - * - * @param runnable - * a {@code Runnable} whose method <code>run</code> will be - * executed by the new {@code Thread} - * - * @see java.lang.ThreadGroup - * @see java.lang.Runnable - */ - public Thread(Runnable runnable) { - create(null, runnable, null, 0); - } - - /** - * Constructs a new {@code Thread} with a {@code Runnable} object and name - * provided. The new {@code Thread} will belong to the same {@code - * ThreadGroup} as the {@code Thread} calling this constructor. - * - * @param runnable - * a {@code Runnable} whose method <code>run</code> will be - * executed by the new {@code Thread} - * @param threadName - * the name for the {@code Thread} being created - * - * @see java.lang.ThreadGroup - * @see java.lang.Runnable - */ - public Thread(Runnable runnable, String threadName) { - if (threadName == null) { - throw new NullPointerException("threadName == null"); - } - - create(null, runnable, threadName, 0); - } - - /** - * Constructs a new {@code Thread} with no {@code Runnable} object and the - * name provided. The new {@code Thread} will belong to the same {@code - * ThreadGroup} as the {@code Thread} calling this constructor. - * - * @param threadName - * the name for the {@code Thread} being created - * - * @see java.lang.ThreadGroup - * @see java.lang.Runnable - * - */ - public Thread(String threadName) { - if (threadName == null) { - throw new NullPointerException("threadName == null"); - } - - create(null, null, threadName, 0); - } - - /** - * Constructs a new {@code Thread} with a {@code Runnable} object and a - * newly generated name. The new {@code Thread} will belong to the {@code - * ThreadGroup} passed as parameter. - * - * @param group - * {@code ThreadGroup} to which the new {@code Thread} will - * belong - * @param runnable - * a {@code Runnable} whose method <code>run</code> will be - * executed by the new {@code Thread} - * @throws IllegalThreadStateException - * if <code>group.destroy()</code> has already been done - * @see java.lang.ThreadGroup - * @see java.lang.Runnable - */ - public Thread(ThreadGroup group, Runnable runnable) { - create(group, runnable, null, 0); - } - - /** - * Constructs a new {@code Thread} with a {@code Runnable} object, the given - * name and belonging to the {@code ThreadGroup} passed as parameter. - * - * @param group - * ThreadGroup to which the new {@code Thread} will belong - * @param runnable - * a {@code Runnable} whose method <code>run</code> will be - * executed by the new {@code Thread} - * @param threadName - * the name for the {@code Thread} being created - * @throws IllegalThreadStateException - * if <code>group.destroy()</code> has already been done - * @see java.lang.ThreadGroup - * @see java.lang.Runnable - */ - public Thread(ThreadGroup group, Runnable runnable, String threadName) { - if (threadName == null) { - throw new NullPointerException("threadName == null"); - } - - create(group, runnable, threadName, 0); - } - - /** - * Constructs a new {@code Thread} with no {@code Runnable} object, the - * given name and belonging to the {@code ThreadGroup} passed as parameter. - * - * @param group - * {@code ThreadGroup} to which the new {@code Thread} will belong - * @param threadName - * the name for the {@code Thread} being created - * @throws IllegalThreadStateException - * if <code>group.destroy()</code> has already been done - * @see java.lang.ThreadGroup - * @see java.lang.Runnable - */ - public Thread(ThreadGroup group, String threadName) { - if (threadName == null) { - throw new NullPointerException("threadName == null"); - } - - create(group, null, threadName, 0); - } - - /** - * Constructs a new {@code Thread} with a {@code Runnable} object, the given - * name and belonging to the {@code ThreadGroup} passed as parameter. - * - * @param group - * {@code ThreadGroup} to which the new {@code Thread} will - * belong - * @param runnable - * a {@code Runnable} whose method <code>run</code> will be - * executed by the new {@code Thread} - * @param threadName - * the name for the {@code Thread} being created - * @param stackSize - * a stack size for the new {@code Thread}. This has a highly - * platform-dependent interpretation. It may even be ignored - * completely. - * @throws IllegalThreadStateException - * if <code>group.destroy()</code> has already been done - * @see java.lang.ThreadGroup - * @see java.lang.Runnable - */ - public Thread(ThreadGroup group, Runnable runnable, String threadName, long stackSize) { - if (threadName == null) { - throw new NullPointerException("threadName == null"); - } - create(group, runnable, threadName, stackSize); - } - - /** - * Package-scope method invoked by Dalvik VM to create "internal" - * threads or attach threads created externally. - * - * Don't call Thread.currentThread(), since there may not be such - * a thing (e.g. for Main). - */ - Thread(ThreadGroup group, String name, int priority, boolean daemon) { - synchronized (Thread.class) { - id = ++Thread.count; - } - - if (name == null) { - this.name = "Thread-" + id; - } else { - this.name = name; - } - - if (group == null) { - throw new InternalError("group not specified"); - } - - this.group = group; - - this.target = null; - this.stackSize = 0; - this.priority = priority; - this.daemon = daemon; - - /* add ourselves to our ThreadGroup of choice */ - this.group.addThread(this); - } - - /** - * Initializes a new, existing Thread object with a runnable object, - * the given name and belonging to the ThreadGroup passed as parameter. - * This is the method that the several public constructors delegate their - * work to. - * - * @param group ThreadGroup to which the new Thread will belong - * @param runnable a java.lang.Runnable whose method <code>run</code> will - * be executed by the new Thread - * @param threadName Name for the Thread being created - * @param stackSize Platform dependent stack size - * @throws IllegalThreadStateException if <code>group.destroy()</code> has - * already been done - * @see java.lang.ThreadGroup - * @see java.lang.Runnable - */ - private void create(ThreadGroup group, Runnable runnable, String threadName, long stackSize) { - Thread currentThread = Thread.currentThread(); - if (group == null) { - group = currentThread.getThreadGroup(); - } - - if (group.isDestroyed()) { - throw new IllegalThreadStateException("Group already destroyed"); - } - - this.group = group; - - synchronized (Thread.class) { - id = ++Thread.count; - } - - if (threadName == null) { - this.name = "Thread-" + id; - } else { - this.name = threadName; - } - - this.target = runnable; - this.stackSize = stackSize; - - this.priority = currentThread.getPriority(); - - this.contextClassLoader = currentThread.contextClassLoader; - - // Transfer over InheritableThreadLocals. - if (currentThread.inheritableValues != null) { - inheritableValues = new ThreadLocal.Values(currentThread.inheritableValues); - } - - // add ourselves to our ThreadGroup of choice - this.group.addThread(this); - } - - /** - * Returns the number of active {@code Thread}s in the running {@code - * Thread}'s group and its subgroups. - * - * @return the number of {@code Thread}s - */ - public static int activeCount() { - return currentThread().getThreadGroup().activeCount(); - } - - /** - * Does nothing. - */ - public final void checkAccess() { - } - - /** - * Returns the number of stack frames in this thread. - * - * @return Number of stack frames - * @deprecated The results of this call were never well defined. To make - * things worse, it would depend on whether the Thread was - * suspended or not, and suspend was deprecated too. - */ - @Deprecated - public int countStackFrames() { - return getStackTrace().length; - } - - /** - * Returns the Thread of the caller, that is, the current Thread. - * - * @return the current Thread. - */ - public static Thread currentThread() { - return VMThread.currentThread(); - } - - /** - * Throws {@code UnsupportedOperationException}. - * @deprecated Not implemented. - */ - @Deprecated - public void destroy() { - throw new UnsupportedOperationException(); - } - - /** - * Prints to the standard error stream a text representation of the current - * stack for this Thread. - * - * @see Throwable#printStackTrace() - */ - public static void dumpStack() { - new Throwable("stack dump").printStackTrace(); - } - - /** - * Copies an array with all Threads which are in the same ThreadGroup as the - * receiver - and subgroups - into the array <code>threads</code> passed as - * parameter. If the array passed as parameter is too small no exception is - * thrown - the extra elements are simply not copied. - * - * @param threads - * array into which the Threads will be copied - * @return How many Threads were copied over - */ - public static int enumerate(Thread[] threads) { - Thread thread = Thread.currentThread(); - return thread.getThreadGroup().enumerate(threads); - } - - /** - * Returns a map of all the currently live threads to their stack traces. - */ - public static Map<Thread, StackTraceElement[]> getAllStackTraces() { - Map<Thread, StackTraceElement[]> map = new HashMap<Thread, StackTraceElement[]>(); - - // Find out how many live threads we have. Allocate a bit more - // space than needed, in case new ones are just being created. - int count = ThreadGroup.mSystem.activeCount(); - Thread[] threads = new Thread[count + count / 2]; - - // Enumerate the threads and collect the stacktraces. - count = ThreadGroup.mSystem.enumerate(threads); - for (int i = 0; i < count; i++) { - map.put(threads[i], threads[i].getStackTrace()); - } - - return map; - } - - /** - * Returns the context ClassLoader for this Thread. - * - * @return ClassLoader The context ClassLoader - * @see java.lang.ClassLoader - * @see #getContextClassLoader() - */ - public ClassLoader getContextClassLoader() { - return contextClassLoader; - } - - /** - * Returns the default exception handler that's executed when uncaught - * exception terminates a thread. - * - * @return an {@link UncaughtExceptionHandler} or <code>null</code> if - * none exists. - */ - public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() { - return defaultUncaughtHandler; - } - - /** - * Returns the thread's identifier. The ID is a positive <code>long</code> - * generated on thread creation, is unique to the thread, and doesn't change - * during the lifetime of the thread; the ID may be reused after the thread - * has been terminated. - * - * @return the thread's ID. - */ - public long getId() { - return id; - } - - /** - * Returns the name of the Thread. - */ - public final String getName() { - return name; - } - - /** - * Returns the priority of the Thread. - */ - public final int getPriority() { - return priority; - } - - /** - * Returns an array of {@link StackTraceElement} representing the current thread's stack. - */ - public StackTraceElement[] getStackTrace() { - StackTraceElement ste[] = VMStack.getThreadStackTrace(this); - return ste != null ? ste : EmptyArray.STACK_TRACE_ELEMENT; - } - - /** - * Returns the current state of the Thread. This method is useful for - * monitoring purposes. - * - * @return a {@link State} value. - */ - public State getState() { - // TODO This is ugly and should be implemented better. - VMThread vmt = this.vmThread; - - // Make sure we have a valid reference to an object. If native code - // deletes the reference we won't run into a null reference later. - VMThread thread = vmThread; - if (thread != null) { - // If the Thread Object became invalid or was not yet started, - // getStatus() will return -1. - int state = thread.getStatus(); - if(state != -1) { - return VMThread.STATE_MAP[state]; - } - } - return hasBeenStarted ? Thread.State.TERMINATED : Thread.State.NEW; - } - - /** - * Returns the ThreadGroup to which this Thread belongs. - * - * @return the Thread's ThreadGroup - */ - public final ThreadGroup getThreadGroup() { - // TODO This should actually be done at native termination. - if (getState() == Thread.State.TERMINATED) { - return null; - } else { - return group; - } - } - - /** - * Returns the thread's uncaught exception handler. If not explicitly set, - * then the ThreadGroup's handler is returned. If the thread is terminated, - * then <code>null</code> is returned. - * - * @return an {@link UncaughtExceptionHandler} instance or {@code null}. - */ - public UncaughtExceptionHandler getUncaughtExceptionHandler() { - if (uncaughtHandler != null) - return uncaughtHandler; - else - return group; // ThreadGroup is instance of UEH - } - - /** - * Posts an interrupt request to this {@code Thread}. The behavior depends on - * the state of this {@code Thread}: - * <ul> - * <li> - * {@code Thread}s blocked in one of {@code Object}'s {@code wait()} methods - * or one of {@code Thread}'s {@code join()} or {@code sleep()} methods will - * be woken up, their interrupt status will be cleared, and they receive an - * {@link InterruptedException}. - * <li> - * {@code Thread}s blocked in an I/O operation of an - * {@link java.nio.channels.InterruptibleChannel} will have their interrupt - * status set and receive an - * {@link java.nio.channels.ClosedByInterruptException}. Also, the channel - * will be closed. - * <li> - * {@code Thread}s blocked in a {@link java.nio.channels.Selector} will have - * their interrupt status set and return immediately. They don't receive an - * exception in this case. - * <ul> - * - * @see Thread#interrupted - * @see Thread#isInterrupted - */ - public void interrupt() { - // Interrupt this thread before running actions so that other - // threads that observe the interrupt as a result of an action - // will see that this thread is in the interrupted state. - VMThread vmt = this.vmThread; - if (vmt != null) { - vmt.interrupt(); - } - - synchronized (interruptActions) { - for (int i = interruptActions.size() - 1; i >= 0; i--) { - interruptActions.get(i).run(); - } - } - } - - /** - * Returns a <code>boolean</code> indicating whether the current Thread ( - * <code>currentThread()</code>) has a pending interrupt request (<code> - * true</code>) or not (<code>false</code>). It also has the side-effect of - * clearing the flag. - * - * @return a <code>boolean</code> indicating the interrupt status - * @see Thread#currentThread - * @see Thread#interrupt - * @see Thread#isInterrupted - */ - public static boolean interrupted() { - return VMThread.interrupted(); - } - - /** - * Returns <code>true</code> if the receiver has already been started and - * still runs code (hasn't died yet). Returns <code>false</code> either if - * the receiver hasn't been started yet or if it has already started and run - * to completion and died. - * - * @return a <code>boolean</code> indicating the liveness of the Thread - * @see Thread#start - */ - public final boolean isAlive() { - return (vmThread != null); - } - - /** - * Tests whether this is a daemon thread. - * A daemon thread only runs as long as there are non-daemon threads running. - * When the last non-daemon thread ends, the runtime will exit. This is not - * normally relevant to applications with a UI. - */ - public final boolean isDaemon() { - return daemon; - } - - /** - * Returns a <code>boolean</code> indicating whether the receiver has a - * pending interrupt request (<code>true</code>) or not ( - * <code>false</code>) - * - * @return a <code>boolean</code> indicating the interrupt status - * @see Thread#interrupt - * @see Thread#interrupted - */ - public boolean isInterrupted() { - VMThread vmt = this.vmThread; - if (vmt != null) { - return vmt.isInterrupted(); - } - - return false; - } - - /** - * Blocks the current Thread (<code>Thread.currentThread()</code>) until - * the receiver finishes its execution and dies. - * - * @throws InterruptedException if the current thread has been interrupted. - * The interrupted status of the current thread will be cleared before the exception is - * thrown. - * @see Object#notifyAll - * @see java.lang.ThreadDeath - */ - public final void join() throws InterruptedException { - VMThread t = vmThread; - if (t == null) { - return; - } - - synchronized (t) { - while (isAlive()) { - t.wait(); - } - } - } - - /** - * Blocks the current Thread (<code>Thread.currentThread()</code>) until - * the receiver finishes its execution and dies or the specified timeout - * expires, whatever happens first. - * - * <p>A timeout of zero means the calling thread should wait forever unless interrupted. - * - * @param millis The maximum time to wait (in milliseconds). - * @throws InterruptedException if the current thread has been interrupted. - * The interrupted status of the current thread will be cleared before the exception is - * thrown. - * @see Object#notifyAll - * @see java.lang.ThreadDeath - */ - public final void join(long millis) throws InterruptedException { - join(millis, 0); - } - - /** - * Blocks the current Thread (<code>Thread.currentThread()</code>) until - * the receiver finishes its execution and dies or the specified timeout - * expires, whatever happens first. - * - * <p>A timeout of zero means the calling thread should wait forever unless interrupted. - * - * @param millis The maximum time to wait (in milliseconds). - * @param nanos Extra nanosecond precision - * @throws InterruptedException if the current thread has been interrupted. - * The interrupted status of the current thread will be cleared before the exception is - * thrown. - * @see Object#notifyAll - * @see java.lang.ThreadDeath - */ - public final void join(long millis, int nanos) throws InterruptedException { - if (millis < 0 || nanos < 0 || nanos >= NANOS_PER_MILLI) { - throw new IllegalArgumentException("bad timeout: millis=" + millis + ",nanos=" + nanos); - } - - // avoid overflow: if total > 292,277 years, just wait forever - boolean overflow = millis >= (Long.MAX_VALUE - nanos) / NANOS_PER_MILLI; - boolean forever = (millis | nanos) == 0; - if (forever | overflow) { - join(); - return; - } - - VMThread t = vmThread; - if (t == null) { - return; - } - - synchronized (t) { - if (!isAlive()) { - return; - } - - // guaranteed not to overflow - long nanosToWait = millis * NANOS_PER_MILLI + nanos; - - // wait until this thread completes or the timeout has elapsed - long start = System.nanoTime(); - while (true) { - t.wait(millis, nanos); - if (!isAlive()) { - break; - } - long nanosElapsed = System.nanoTime() - start; - long nanosRemaining = nanosToWait - nanosElapsed; - if (nanosRemaining <= 0) { - break; - } - millis = nanosRemaining / NANOS_PER_MILLI; - nanos = (int) (nanosRemaining - millis * NANOS_PER_MILLI); - } - } - } - - /** - * Throws {@code UnsupportedOperationException}. - * @deprecated Only useful in conjunction with deprecated method {@link Thread#suspend}. - */ - @Deprecated - public final void resume() { - throw new UnsupportedOperationException(); - } - - /** - * Calls the <code>run()</code> method of the Runnable object the receiver - * holds. If no Runnable is set, does nothing. - * - * @see Thread#start - */ - public void run() { - if (target != null) { - target.run(); - } - } - - /** - * Set the context ClassLoader for the receiver. - * - * @param cl The context ClassLoader - * @see #getContextClassLoader() - */ - public void setContextClassLoader(ClassLoader cl) { - contextClassLoader = cl; - } - - /** - * Marks this thread as a daemon thread. - * A daemon thread only runs as long as there are non-daemon threads running. - * When the last non-daemon thread ends, the runtime will exit. This is not - * normally relevant to applications with a UI. - * @throws IllegalThreadStateException - if this thread has already started. - */ - public final void setDaemon(boolean isDaemon) { - checkNotStarted(); - if (vmThread == null) { - daemon = isDaemon; - } - } - - private void checkNotStarted() { - if (hasBeenStarted) { - throw new IllegalThreadStateException("Thread already started"); - } - } - - /** - * Sets the default uncaught exception handler. This handler is invoked in - * case any Thread dies due to an unhandled exception. - * - * @param handler - * The handler to set or null. - */ - public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) { - Thread.defaultUncaughtHandler = handler; - } - - /** - * Adds a runnable to be invoked upon interruption. If this thread has - * already been interrupted, the runnable will be invoked immediately. The - * action should be idempotent as it may be invoked multiple times for a - * single interruption. - * - * <p>Each call to this method must be matched with a corresponding call to - * {@link #popInterruptAction$}. - * - * @hide used by NIO - */ - public final void pushInterruptAction$(Runnable interruptAction) { - synchronized (interruptActions) { - interruptActions.add(interruptAction); - } - - if (interruptAction != null && isInterrupted()) { - interruptAction.run(); - } - } - - /** - * Removes {@code interruptAction} so it is not invoked upon interruption. - * - * @param interruptAction the pushed action, used to check that the call - * stack is correctly nested. - * - * @hide used by NIO - */ - public final void popInterruptAction$(Runnable interruptAction) { - synchronized (interruptActions) { - Runnable removed = interruptActions.remove(interruptActions.size() - 1); - if (interruptAction != removed) { - throw new IllegalArgumentException( - "Expected " + interruptAction + " but was " + removed); - } - } - } - - /** - * Sets the name of the Thread. - * - * @param threadName the new name for the Thread - * @see Thread#getName - */ - public final void setName(String threadName) { - if (threadName == null) { - throw new NullPointerException("threadName == null"); - } - - name = threadName; - VMThread vmt = this.vmThread; - if (vmt != null) { - /* notify the VM that the thread name has changed */ - vmt.nameChanged(threadName); - } - } - - /** - * Sets the priority of this thread. If the requested priority is greater than the - * parent thread group's {@link java.lang.ThreadGroup#getMaxPriority}, the group's maximum - * priority will be used instead. - * - * @throws IllegalArgumentException - if the new priority is greater than {@link #MAX_PRIORITY} - * or less than {@link #MIN_PRIORITY} - */ - public final void setPriority(int priority) { - if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) { - throw new IllegalArgumentException("Priority out of range: " + priority); - } - - if (priority > group.getMaxPriority()) { - priority = group.getMaxPriority(); - } - - this.priority = priority; - - VMThread vmt = this.vmThread; - if (vmt != null) { - vmt.setPriority(priority); - } - } - - /** - * <p> - * Sets the uncaught exception handler. This handler is invoked in case this - * Thread dies due to an unhandled exception. - * </p> - * - * @param handler - * The handler to set or <code>null</code>. - */ - public void setUncaughtExceptionHandler(UncaughtExceptionHandler handler) { - uncaughtHandler = handler; - } - - /** - * Causes the thread which sent this message to sleep for the given interval - * of time (given in milliseconds). The precision is not guaranteed - the - * Thread may sleep more or less than requested. - * - * @param time - * The time to sleep in milliseconds. - * @throws InterruptedException if the current thread has been interrupted. - * The interrupted status of the current thread will be cleared before the exception - * is thrown. - * @see Thread#interrupt() - */ - public static void sleep(long time) throws InterruptedException { - Thread.sleep(time, 0); - } - - /** - * Causes the thread which sent this message to sleep for the given interval - * of time (given in milliseconds and nanoseconds). The precision is not - * guaranteed - the Thread may sleep more or less than requested. - * - * @param millis - * The time to sleep in milliseconds. - * @param nanos - * Extra nanosecond precision - * @throws InterruptedException if the current thread has been interrupted. - * The interrupted status of the current thread will be cleared before the exception - * is thrown. - * @see Thread#interrupt() - */ - public static void sleep(long millis, int nanos) throws InterruptedException { - VMThread.sleep(millis, nanos); - } - - /** - * Starts the new Thread of execution. The <code>run()</code> method of - * the receiver will be called by the receiver Thread itself (and not the - * Thread calling <code>start()</code>). - * - * @throws IllegalThreadStateException - if this thread has already started. - * @see Thread#run - */ - public synchronized void start() { - checkNotStarted(); - - hasBeenStarted = true; - - VMThread.create(this, stackSize); - } - - /** - * Requests the receiver Thread to stop and throw ThreadDeath. The Thread is - * resumed if it was suspended and awakened if it was sleeping, so that it - * can proceed to throw ThreadDeath. - * - * @deprecated Stopping a thread in this manner is unsafe and can - * leave your application and the VM in an unpredictable state. - */ - @Deprecated - public final void stop() { - stop(new ThreadDeath()); - } - - /** - * Throws {@code UnsupportedOperationException}. - * @deprecated Stopping a thread in this manner is unsafe and can - * leave your application and the VM in an unpredictable state. - */ - @Deprecated - public final synchronized void stop(Throwable throwable) { - throw new UnsupportedOperationException(); - } - - /** - * Throws {@code UnsupportedOperationException}. - * @deprecated May cause deadlocks. - */ - @Deprecated - public final void suspend() { - throw new UnsupportedOperationException(); - } - - /** - * Returns a string containing a concise, human-readable description of the - * Thread. It includes the Thread's name, priority, and group name. - * - * @return a printable representation for the receiver. - */ - @Override - public String toString() { - return "Thread[" + name + "," + priority + "," + group.getName() + "]"; - } - - /** - * Causes the calling Thread to yield execution time to another Thread that - * is ready to run. The actual scheduling is implementation-dependent. - */ - public static void yield() { - VMThread.yield(); - } - - /** - * Indicates whether the current Thread has a monitor lock on the specified - * object. - * - * @param object the object to test for the monitor lock - * @return true if the current thread has a monitor lock on the specified - * object; false otherwise - */ - public static boolean holdsLock(Object object) { - return currentThread().vmThread.holdsLock(object); - } - - /** - * Implemented by objects that want to handle cases where a thread is being - * terminated by an uncaught exception. Upon such termination, the handler - * is notified of the terminating thread and causal exception. If there is - * no explicit handler set then the thread's group is the default handler. - */ - public static interface UncaughtExceptionHandler { - /** - * The thread is being terminated by an uncaught exception. Further - * exceptions thrown in this method are prevent the remainder of the - * method from executing, but are otherwise ignored. - * - * @param thread the thread that has an uncaught exception - * @param ex the exception that was thrown - */ - void uncaughtException(Thread thread, Throwable ex); - } - - /** - * Unparks this thread. This unblocks the thread it if it was - * previously parked, or indicates that the thread is "preemptively - * unparked" if it wasn't already parked. The latter means that the - * next time the thread is told to park, it will merely clear its - * latent park bit and carry on without blocking. - * - * <p>See {@link java.util.concurrent.locks.LockSupport} for more - * in-depth information of the behavior of this method.</p> - * - * @hide for Unsafe - */ - public void unpark() { - VMThread vmt = vmThread; - - if (vmt == null) { - /* - * vmThread is null before the thread is start()ed. In - * this case, we just go ahead and set the state to - * PREEMPTIVELY_UNPARKED. Since this happens before the - * thread is started, we don't have to worry about - * synchronizing with it. - */ - parkState = ParkState.PREEMPTIVELY_UNPARKED; - return; - } - - synchronized (vmt) { - switch (parkState) { - case ParkState.PREEMPTIVELY_UNPARKED: { - /* - * Nothing to do in this case: By definition, a - * preemptively unparked thread is to remain in - * the preemptively unparked state if it is told - * to unpark. - */ - break; - } - case ParkState.UNPARKED: { - parkState = ParkState.PREEMPTIVELY_UNPARKED; - break; - } - default /*parked*/: { - parkState = ParkState.UNPARKED; - vmt.notifyAll(); - break; - } - } - } - } - - /** - * Parks the current thread for a particular number of nanoseconds, or - * indefinitely. If not indefinitely, this method unparks the thread - * after the given number of nanoseconds if no other thread unparks it - * first. If the thread has been "preemptively unparked," this method - * cancels that unparking and returns immediately. This method may - * also return spuriously (that is, without the thread being told to - * unpark and without the indicated amount of time elapsing). - * - * <p>See {@link java.util.concurrent.locks.LockSupport} for more - * in-depth information of the behavior of this method.</p> - * - * <p>This method must only be called when <code>this</code> is the current - * thread. - * - * @param nanos number of nanoseconds to park for or <code>0</code> - * to park indefinitely - * @throws IllegalArgumentException thrown if <code>nanos < 0</code> - * - * @hide for Unsafe - */ - public void parkFor(long nanos) { - VMThread vmt = vmThread; - - if (vmt == null) { - // Running threads should always have an associated vmThread. - throw new AssertionError(); - } - - synchronized (vmt) { - switch (parkState) { - case ParkState.PREEMPTIVELY_UNPARKED: { - parkState = ParkState.UNPARKED; - break; - } - case ParkState.UNPARKED: { - long millis = nanos / NANOS_PER_MILLI; - nanos %= NANOS_PER_MILLI; - - parkState = ParkState.PARKED; - try { - vmt.wait(millis, (int) nanos); - } catch (InterruptedException ex) { - interrupt(); - } finally { - /* - * Note: If parkState manages to become - * PREEMPTIVELY_UNPARKED before hitting this - * code, it should left in that state. - */ - if (parkState == ParkState.PARKED) { - parkState = ParkState.UNPARKED; - } - } - break; - } - default /*parked*/: { - throw new AssertionError( - "shouldn't happen: attempt to repark"); - } - } - } - } - - /** - * Parks the current thread until the specified system time. This - * method attempts to unpark the current thread immediately after - * <code>System.currentTimeMillis()</code> reaches the specified - * value, if no other thread unparks it first. If the thread has - * been "preemptively unparked," this method cancels that - * unparking and returns immediately. This method may also return - * spuriously (that is, without the thread being told to unpark - * and without the indicated amount of time elapsing). - * - * <p>See {@link java.util.concurrent.locks.LockSupport} for more - * in-depth information of the behavior of this method.</p> - * - * <p>This method must only be called when <code>this</code> is the - * current thread. - * - * @param time the time after which the thread should be unparked, - * in absolute milliseconds-since-the-epoch - * - * @hide for Unsafe - */ - public void parkUntil(long time) { - VMThread vmt = vmThread; - - if (vmt == null) { - // Running threads should always have an associated vmThread. - throw new AssertionError(); - } - - synchronized (vmt) { - /* - * Note: This conflates the two time bases of "wall clock" - * time and "monotonic uptime" time. However, given that - * the underlying system can only wait on monotonic time, - * it is unclear if there is any way to avoid the - * conflation. The downside here is that if, having - * calculated the delay, the wall clock gets moved ahead, - * this method may not return until well after the wall - * clock has reached the originally designated time. The - * reverse problem (the wall clock being turned back) - * isn't a big deal, since this method is allowed to - * spuriously return for any reason, and this situation - * can safely be construed as just such a spurious return. - */ - long delayMillis = time - System.currentTimeMillis(); - - if (delayMillis <= 0) { - parkState = ParkState.UNPARKED; - } else { - parkFor(delayMillis * NANOS_PER_MILLI); - } - } - } -} diff --git a/libdvm/src/main/java/java/lang/ThreadGroup.java b/libdvm/src/main/java/java/lang/ThreadGroup.java deleted file mode 100644 index 7fc6b72..0000000 --- a/libdvm/src/main/java/java/lang/ThreadGroup.java +++ /dev/null @@ -1,726 +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. - */ - -package java.lang; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import libcore.util.CollectionUtils; - -/** - * {@code ThreadGroup} is a means of organizing threads into a hierarchical structure. - * This class is obsolete. See <i>Effective Java</i> Item 73, "Avoid thread groups" for details. - * @see Thread - */ -public class ThreadGroup implements Thread.UncaughtExceptionHandler { - - // Name of this ThreadGroup - // VM needs this field name for debugging. - private String name; - - // Maximum priority for Threads inside this ThreadGroup - private int maxPriority = Thread.MAX_PRIORITY; - - // The ThreadGroup to which this ThreadGroup belongs - // VM needs this field name for debugging. - final ThreadGroup parent; - - /** - * Weak references to the threads in this group. - * Access is guarded by synchronizing on this field. - */ - private final List<WeakReference<Thread>> threadRefs = new ArrayList<WeakReference<Thread>>(5); - - /** - * View of the threads. - * Access is guarded by synchronizing on threadRefs. - */ - private final Iterable<Thread> threads = CollectionUtils.dereferenceIterable(threadRefs, true); - - /** - * Thread groups. Access is guarded by synchronizing on this field. - */ - private final List<ThreadGroup> groups = new ArrayList<ThreadGroup>(3); - - // Whether this ThreadGroup is a daemon ThreadGroup or not - private boolean isDaemon; - - // Whether this ThreadGroup has already been destroyed or not - private boolean isDestroyed; - - /* the VM uses these directly; do not rename */ - static final ThreadGroup mSystem = new ThreadGroup(); - static final ThreadGroup mMain = new ThreadGroup(mSystem, "main"); - - /** - * Constructs a new {@code ThreadGroup} with the given name. The new {@code ThreadGroup} - * will be child of the {@code ThreadGroup} to which the calling thread belongs. - * - * @param name the name - * @see Thread#currentThread - */ - public ThreadGroup(String name) { - this(Thread.currentThread().getThreadGroup(), name); - } - - /** - * Constructs a new {@code ThreadGroup} with the given name, as a child of the - * given {@code ThreadGroup}. - * - * @param parent the parent - * @param name the name - * @throws NullPointerException if {@code parent == null} - * @throws IllegalThreadStateException if {@code parent} has been - * destroyed already - */ - public ThreadGroup(ThreadGroup parent, String name) { - if (parent == null) { - throw new NullPointerException("parent == null"); - } - this.name = name; - this.parent = parent; - if (parent != null) { - parent.add(this); - this.setMaxPriority(parent.getMaxPriority()); - if (parent.isDaemon()) { - this.setDaemon(true); - } - } - } - - /** - * Initialize the special "system" ThreadGroup. Was "main" in Harmony, - * but we have an additional group above that in Android. - */ - private ThreadGroup() { - this.name = "system"; - this.parent = null; - } - - /** - * Returns the number of running {@code Thread}s which are children of this thread group, - * directly or indirectly. - * - * @return the number of children - */ - public int activeCount() { - int count = 0; - synchronized (threadRefs) { - for (Thread thread : threads) { - if (thread.isAlive()) { - count++; - } - } - } - synchronized (groups) { - for (ThreadGroup group : groups) { - count += group.activeCount(); - } - } - return count; - } - - /** - * Returns the number of {@code ThreadGroup}s which are children of this group, - * directly or indirectly. - * - * @return the number of children - */ - public int activeGroupCount() { - int count = 0; - synchronized (groups) { - for (ThreadGroup group : groups) { - // One for this group & the subgroups - count += 1 + group.activeGroupCount(); - } - } - return count; - } - - /** - * Adds a {@code ThreadGroup} to this thread group. - * - * @param g ThreadGroup to add - * @throws IllegalThreadStateException if this group has been destroyed already - */ - private void add(ThreadGroup g) throws IllegalThreadStateException { - synchronized (groups) { - if (isDestroyed) { - throw new IllegalThreadStateException(); - } - groups.add(g); - } - } - - /** - * Does nothing. The definition of this method depends on the deprecated - * method {@link #suspend()}. The exact behavior of this call was never - * specified. - * - * @param b Used to control low memory implicit suspension - * @return {@code true} (always) - * - * @deprecated Required deprecated method {@link #suspend()}. - */ - @Deprecated - public boolean allowThreadSuspension(boolean b) { - // Does not apply to this VM, no-op - return true; - } - - /** - * Does nothing. - */ - public final void checkAccess() { - } - - /** - * Destroys this thread group and recursively all its subgroups. It is only legal - * to destroy a {@code ThreadGroup} that has no threads in it. Any daemon - * {@code ThreadGroup} is destroyed automatically when it becomes empty (no threads - * or thread groups in it). - * - * @throws IllegalThreadStateException if this thread group or any of its - * subgroups has been destroyed already or if it still contains - * threads. - */ - public final void destroy() { - synchronized (threadRefs) { - synchronized (groups) { - if (isDestroyed) { - throw new IllegalThreadStateException( - "Thread group was already destroyed: " - + (this.name != null ? this.name : "n/a")); - } - if (threads.iterator().hasNext()) { - throw new IllegalThreadStateException( - "Thread group still contains threads: " - + (this.name != null ? this.name : "n/a")); - } - // Call recursively for subgroups - while (!groups.isEmpty()) { - // We always get the first element - remember, when the - // child dies it removes itself from our collection. See - // below. - groups.get(0).destroy(); - } - - if (parent != null) { - parent.remove(this); - } - - // Now that the ThreadGroup is really destroyed it can be tagged as so - this.isDestroyed = true; - } - } - } - - /* - * Auxiliary method that destroys this thread group and recursively all its - * subgroups if this is a daemon ThreadGroup. - * - * @see #destroy - * @see #setDaemon - * @see #isDaemon - */ - private void destroyIfEmptyDaemon() { - // Has to be non-destroyed daemon to make sense - synchronized (threadRefs) { - if (isDaemon && !isDestroyed && !threads.iterator().hasNext()) { - synchronized (groups) { - if (groups.isEmpty()) { - destroy(); - } - } - } - } - } - - /** - * Iterates over all active threads in this group (and its sub-groups) and - * stores the threads in the given array. Returns when the array is full or - * no more threads remain, whichever happens first. - * - * <p>Note that this method will silently ignore any threads that don't fit in the - * supplied array. - * - * @param threads the array into which the {@code Thread}s will be copied - * @return the number of {@code Thread}s that were copied - */ - public int enumerate(Thread[] threads) { - return enumerate(threads, true); - } - - /** - * Iterates over all active threads in this group (and, optionally, its - * sub-groups) and stores the threads in the given array. Returns when the - * array is full or no more threads remain, whichever happens first. - * - * <p>Note that this method will silently ignore any threads that don't fit in the - * supplied array. - * - * @param threads the array into which the {@code Thread}s will be copied - * @param recurse indicates whether {@code Thread}s in subgroups should be - * recursively copied as well - * @return the number of {@code Thread}s that were copied - */ - public int enumerate(Thread[] threads, boolean recurse) { - return enumerateGeneric(threads, recurse, 0, true); - } - - /** - * Iterates over all thread groups in this group (and its sub-groups) and - * and stores the groups in the given array. Returns when the array is full - * or no more groups remain, whichever happens first. - * - * <p>Note that this method will silently ignore any thread groups that don't fit in the - * supplied array. - * - * @param groups the array into which the {@code ThreadGroup}s will be copied - * @return the number of {@code ThreadGroup}s that were copied - */ - public int enumerate(ThreadGroup[] groups) { - return enumerate(groups, true); - } - - /** - * Iterates over all thread groups in this group (and, optionally, its - * sub-groups) and stores the groups in the given array. Returns when - * the array is full or no more groups remain, whichever happens first. - * - * <p>Note that this method will silently ignore any thread groups that don't fit in the - * supplied array. - * - * @param groups the array into which the {@code ThreadGroup}s will be copied - * @param recurse indicates whether {@code ThreadGroup}s in subgroups should be - * recursively copied as well or not - * @return the number of {@code ThreadGroup}s that were copied - */ - public int enumerate(ThreadGroup[] groups, boolean recurse) { - return enumerateGeneric(groups, recurse, 0, false); - } - - /** - * Copies into <param>enumeration</param> starting at - * <param>enumerationIndex</param> all Threads or ThreadGroups in the - * receiver. If <param>recurse</param> is true, recursively enumerate the - * elements in subgroups. - * - * If the array passed as parameter is too small no exception is thrown - - * the extra elements are simply not copied. - * - * @param enumeration array into which the elements will be copied - * @param recurse Indicates whether subgroups should be enumerated or not - * @param enumerationIndex Indicates in which position of the enumeration - * array we are - * @param enumeratingThreads Indicates whether we are enumerating Threads or - * ThreadGroups - * @return How many elements were enumerated/copied over - */ - private int enumerateGeneric(Object[] enumeration, boolean recurse, int enumerationIndex, - boolean enumeratingThreads) { - if (enumeratingThreads) { - synchronized (threadRefs) { - // walk the references directly so we can iterate in reverse order - for (int i = threadRefs.size() - 1; i >= 0; --i) { - Thread thread = threadRefs.get(i).get(); - if (thread != null && thread.isAlive()) { - if (enumerationIndex >= enumeration.length) { - return enumerationIndex; - } - enumeration[enumerationIndex++] = thread; - } - } - } - } else { - synchronized (groups) { - for (int i = groups.size() - 1; i >= 0; --i) { - if (enumerationIndex >= enumeration.length) { - return enumerationIndex; - } - enumeration[enumerationIndex++] = groups.get(i); - } - } - } - - if (recurse) { - synchronized (groups) { - for (ThreadGroup group : groups) { - if (enumerationIndex >= enumeration.length) { - return enumerationIndex; - } - enumerationIndex = group.enumerateGeneric(enumeration, recurse, - enumerationIndex, enumeratingThreads); - } - } - } - return enumerationIndex; - } - - /** - * Returns the maximum allowed priority for a {@code Thread} in this thread group. - * - * @return the maximum priority - * - * @see #setMaxPriority - */ - public final int getMaxPriority() { - return maxPriority; - } - - /** - * Returns the name of this thread group. - * - * @return the group's name - */ - public final String getName() { - return name; - } - - /** - * Returns this thread group's parent {@code ThreadGroup}. It can be null if this - * is the the root ThreadGroup. - * - * @return the parent - */ - public final ThreadGroup getParent() { - return parent; - } - - /** - * Interrupts every {@code Thread} in this group and recursively in all its - * subgroups. - * - * @see Thread#interrupt - */ - public final void interrupt() { - synchronized (threadRefs) { - for (Thread thread : threads) { - thread.interrupt(); - } - } - synchronized (groups) { - for (ThreadGroup group : groups) { - group.interrupt(); - } - } - } - - /** - * Checks whether this thread group is a daemon {@code ThreadGroup}. - * - * @return true if this thread group is a daemon {@code ThreadGroup} - * - * @see #setDaemon - * @see #destroy - */ - public final boolean isDaemon() { - return isDaemon; - } - - /** - * Checks whether this thread group has already been destroyed. - * - * @return true if this thread group has already been destroyed - * @see #destroy - */ - public synchronized boolean isDestroyed() { - return isDestroyed; - } - - /** - * Outputs to {@code System.out} a text representation of the - * hierarchy of {@code Thread}s and {@code ThreadGroup}s in this thread group (and recursively). - * Proper indentation is used to show the nesting of groups inside groups - * and threads inside groups. - */ - public void list() { - // We start in a fresh line - System.out.println(); - list(0); - } - - /* - * Outputs to {@code System.out}a text representation of the - * hierarchy of Threads and ThreadGroups in this thread group (and recursively). - * The indentation will be four spaces per level of nesting. - * - * @param levels How many levels of nesting, so that proper indentation can - * be output. - */ - private void list(int levels) { - indent(levels); - System.out.println(this.toString()); - - ++levels; - synchronized (threadRefs) { - for (Thread thread : threads) { - indent(levels); - System.out.println(thread); - } - } - synchronized (groups) { - for (ThreadGroup group : groups) { - group.list(levels); - } - } - } - - private void indent(int levels) { - for (int i = 0; i < levels; i++) { - System.out.print(" "); // 4 spaces for each level - } - } - - /** - * Checks whether this thread group is a direct or indirect parent group of a - * given {@code ThreadGroup}. - * - * @param g the potential child {@code ThreadGroup} - * @return true if this thread group is parent of {@code g} - */ - public final boolean parentOf(ThreadGroup g) { - while (g != null) { - if (this == g) { - return true; - } - g = g.parent; - } - return false; - } - - /** - * Removes an immediate subgroup. - * - * @param g ThreadGroup to remove - * - * @see #add(Thread) - * @see #add(ThreadGroup) - */ - private void remove(ThreadGroup g) { - synchronized (groups) { - for (Iterator<ThreadGroup> i = groups.iterator(); i.hasNext(); ) { - ThreadGroup threadGroup = i.next(); - if (threadGroup.equals(g)) { - i.remove(); - break; - } - } - } - destroyIfEmptyDaemon(); - } - - /** - * Resumes every thread in this group and recursively in all its - * subgroups. - * - * @see Thread#resume - * @see #suspend - * - * @deprecated Requires deprecated method {@link Thread#resume()}. - */ - @SuppressWarnings("deprecation") - @Deprecated - public final void resume() { - synchronized (threadRefs) { - for (Thread thread : threads) { - thread.resume(); - } - } - synchronized (groups) { - for (ThreadGroup group : groups) { - group.resume(); - } - } - } - - /** - * Sets whether this is a daemon {@code ThreadGroup} or not. Daemon - * thread groups are automatically destroyed when they become empty. - * - * @param isDaemon the new value - * @see #isDaemon - * @see #destroy - */ - public final void setDaemon(boolean isDaemon) { - this.isDaemon = isDaemon; - } - - /** - * Configures the maximum allowed priority for a {@code Thread} in this group and - * recursively in all its subgroups. - * - * <p>A caller can never increase the maximum priority of a thread group. - * Such an attempt will not result in an exception, it will - * simply leave the thread group with its current maximum priority. - * - * @param newMax the new maximum priority to be set - * - * @throws IllegalArgumentException if the new priority is greater than - * Thread.MAX_PRIORITY or less than Thread.MIN_PRIORITY - * - * @see #getMaxPriority - */ - public final void setMaxPriority(int newMax) { - if (newMax <= this.maxPriority) { - if (newMax < Thread.MIN_PRIORITY) { - newMax = Thread.MIN_PRIORITY; - } - - int parentPriority = parent == null ? newMax : parent.getMaxPriority(); - this.maxPriority = parentPriority <= newMax ? parentPriority : newMax; - synchronized (groups) { - for (ThreadGroup group : groups) { - group.setMaxPriority(newMax); - } - } - } - } - - /** - * Stops every thread in this group and recursively in all its subgroups. - * - * @see Thread#stop() - * @see Thread#stop(Throwable) - * @see ThreadDeath - * - * @deprecated Requires deprecated method {@link Thread#stop()}. - */ - @SuppressWarnings("deprecation") - @Deprecated - public final void stop() { - if (stopHelper()) { - Thread.currentThread().stop(); - } - } - - @SuppressWarnings("deprecation") - private boolean stopHelper() { - boolean stopCurrent = false; - synchronized (threadRefs) { - Thread current = Thread.currentThread(); - for (Thread thread : threads) { - if (thread == current) { - stopCurrent = true; - } else { - thread.stop(); - } - } - } - synchronized (groups) { - for (ThreadGroup group : groups) { - stopCurrent |= group.stopHelper(); - } - } - return stopCurrent; - } - - /** - * Suspends every thread in this group and recursively in all its - * subgroups. - * - * @see Thread#suspend - * @see #resume - * - * @deprecated Requires deprecated method {@link Thread#suspend()}. - */ - @SuppressWarnings("deprecation") - @Deprecated - public final void suspend() { - if (suspendHelper()) { - Thread.currentThread().suspend(); - } - } - - @SuppressWarnings("deprecation") - private boolean suspendHelper() { - boolean suspendCurrent = false; - synchronized (threadRefs) { - Thread current = Thread.currentThread(); - for (Thread thread : threads) { - if (thread == current) { - suspendCurrent = true; - } else { - thread.suspend(); - } - } - } - synchronized (groups) { - for (ThreadGroup group : groups) { - suspendCurrent |= group.suspendHelper(); - } - } - return suspendCurrent; - } - - @Override - public String toString() { - return getClass().getName() + "[name=" + getName() - + ",maxPriority=" + getMaxPriority() + "]"; - } - - /** - * Handles uncaught exceptions. Any uncaught exception in any {@code Thread} - * is forwarded to the thread's {@code ThreadGroup} by invoking this - * method. - * - * <p>New code should use {@link Thread#setUncaughtExceptionHandler} instead of thread groups. - * - * @param t the Thread that terminated with an uncaught exception - * @param e the uncaught exception itself - */ - public void uncaughtException(Thread t, Throwable e) { - if (parent != null) { - parent.uncaughtException(t, e); - } else if (Thread.getDefaultUncaughtExceptionHandler() != null) { - // TODO The spec is unclear regarding this. What do we do? - Thread.getDefaultUncaughtExceptionHandler().uncaughtException(t, e); - } else if (!(e instanceof ThreadDeath)) { - // No parent group, has to be 'system' Thread Group - e.printStackTrace(System.err); - } - } - - /** - * Called by the Thread constructor. - */ - final void addThread(Thread thread) throws IllegalThreadStateException { - synchronized (threadRefs) { - if (isDestroyed) { - throw new IllegalThreadStateException(); - } - threadRefs.add(new WeakReference<Thread>(thread)); - } - } - - /** - * Called by the VM when a Thread dies. - */ - final void removeThread(Thread thread) throws IllegalThreadStateException { - synchronized (threadRefs) { - for (Iterator<Thread> i = threads.iterator(); i.hasNext(); ) { - if (i.next().equals(thread)) { - i.remove(); - break; - } - } - } - destroyIfEmptyDaemon(); - } -} diff --git a/libdvm/src/main/java/java/lang/VMClassLoader.java b/libdvm/src/main/java/java/lang/VMClassLoader.java deleted file mode 100644 index d7162c6..0000000 --- a/libdvm/src/main/java/java/lang/VMClassLoader.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2007 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; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; - -class VMClassLoader { - - /** - * Get a resource from a file in the bootstrap class path. - * - * It would be simpler to just walk through the class path elements - * ourselves, but that would require reopening Jar files. - * - * We assume that the bootclasspath can't change once the VM has - * started. This assumption seems to be supported by the spec. - */ - static URL getResource(String name) { - int numEntries = getBootClassPathSize(); - for (int i = 0; i < numEntries; i++) { - String urlStr = getBootClassPathResource(name, i); - if (urlStr != null) { - try { - return new URL(urlStr); - } catch (MalformedURLException mue) { - mue.printStackTrace(); - // unexpected; keep going - } - } - } - return null; - } - - /* - * Get an enumeration with all matching resources. - */ - static List<URL> getResources(String name) { - ArrayList<URL> list = new ArrayList<URL>(); - int numEntries = getBootClassPathSize(); - for (int i = 0; i < numEntries; i++) { - String urlStr = getBootClassPathResource(name, i); - if (urlStr != null) { - try { - list.add(new URL(urlStr)); - } catch (MalformedURLException mue) { - mue.printStackTrace(); - // unexpected; keep going - } - } - } - return list; - } - - /** - * Load class with bootstrap class loader. - */ - native static Class loadClass(String name, boolean resolve) throws ClassNotFoundException; - - native static Class getPrimitiveClass(char type); - - native static Class findLoadedClass(ClassLoader cl, String name); - - /** - * Boot class path manipulation, for getResources(). - */ - native private static int getBootClassPathSize(); - native private static String getBootClassPathResource(String name, int index); -} diff --git a/libdvm/src/main/java/java/lang/VMThread.java b/libdvm/src/main/java/java/lang/VMThread.java deleted file mode 100644 index 01f6ee3..0000000 --- a/libdvm/src/main/java/java/lang/VMThread.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2007 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; - -class VMThread { - Thread thread; - int vmData; - - VMThread(Thread t) { - thread = t; - } - - native static void create(Thread t, long stackSize); - - static native Thread currentThread(); - static native boolean interrupted(); - static native void sleep (long msec, int nsec) throws InterruptedException; - static native void yield(); - - native void interrupt(); - - native boolean isInterrupted(); - - /** - * Starts the VMThread (and thus the Java Thread) with the given - * stack size. - */ - void start(long stackSize) { - VMThread.create(thread, stackSize); - } - - /** - * Queries whether this Thread holds a monitor lock on the - * given object. - */ - native boolean holdsLock(Object object); - - native void setPriority(int newPriority); - native int getStatus(); - - /** - * Holds a mapping from native Thread statuses to Java one. Required for - * translating back the result of getStatus(). - */ - static final Thread.State[] STATE_MAP = new Thread.State[] { - Thread.State.TERMINATED, // ZOMBIE - Thread.State.RUNNABLE, // RUNNING - Thread.State.TIMED_WAITING, // TIMED_WAIT - Thread.State.BLOCKED, // MONITOR - Thread.State.WAITING, // WAIT - Thread.State.NEW, // INITIALIZING - Thread.State.NEW, // STARTING - Thread.State.RUNNABLE, // NATIVE - Thread.State.WAITING, // VMWAIT - Thread.State.RUNNABLE // SUSPENDED - }; - - /** - * Tell the VM that the thread's name has changed. This is useful for - * DDMS, which would otherwise be oblivious to Thread.setName calls. - */ - native void nameChanged(String newName); -} diff --git a/libdvm/src/main/java/java/lang/ref/Reference.java b/libdvm/src/main/java/java/lang/ref/Reference.java deleted file mode 100644 index bd63535..0000000 --- a/libdvm/src/main/java/java/lang/ref/Reference.java +++ /dev/null @@ -1,200 +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.ref; - -/** - * Provides an abstract class which describes behavior common to all reference - * objects. It is not possible to create immediate subclasses of - * {@code Reference} in addition to the ones provided by this package. It is - * also not desirable to do so, since references require very close cooperation - * with the system's garbage collector. The existing, specialized reference - * classes should be used instead. - * - * <p>Three different type of references exist, each being weaker than the preceding one: - * {@link java.lang.ref.SoftReference}, {@link java.lang.ref.WeakReference}, and - * {@link java.lang.ref.PhantomReference}. "Weakness" here means that less restrictions are - * being imposed on the garbage collector as to when it is allowed to - * actually garbage-collect the referenced object. - * - * <p>In order to use reference objects properly it is important to understand - * the different types of reachability that trigger their clearing and - * enqueueing. The following table lists these, from strongest to weakest. - * For each row, an object is said to have the reachability on the left side - * if (and only if) it fulfills all of the requirements on the right side. In - * all rows, consider the <em>root set</em> to be a set of references that - * are "resistant" to garbage collection (that is, running threads, method - * parameters, local variables, static fields and the like). - * - * <p><table> - * <tr> - * <td>Strongly reachable</td> - * <td> <ul> - * <li>There exists at least one path from the root set to the object that does not traverse any - * instance of a {@code java.lang.ref.Reference} subclass. - * </li> - * </ul> </td> - * </tr> - * - * <tr> - * <td>Softly reachable</td> - * <td> <ul> - * <li>The object is not strongly reachable.</li> - * <li>There exists at least one path from the root set to the object that does traverse - * a {@code java.lang.ref.SoftReference} instance, but no {@code java.lang.ref.WeakReference} - * or {@code java.lang.ref.PhantomReference} instances.</li> - * </ul> </td> - * </tr> - * - * <tr> - * <td>Weakly reachable</td> - * <td> <ul> - * <li>The object is neither strongly nor softly reachable.</li> - * <li>There exists at least one path from the root set to the object that does traverse a - * {@code java.lang.ref.WeakReference} instance, but no {@code java.lang.ref.PhantomReference} - * instances.</li> - * </ul> </td> - * </tr> - * - * <tr> - * <td>Phantom-reachable</td> - * <td> <ul> - * <li>The object is neither strongly, softly, nor weakly reachable.</li> - * <li>The object is referenced by a {@code java.lang.ref.PhantomReference} instance.</li> - * <li>The object has already been finalized.</li> - * </ul> </td> - * </tr> - * </table> - */ -public abstract class Reference<T> { - - /** - * The object to which this reference refers. - * VM requirement: this field <em>must</em> be called "referent" - * and be an object. - */ - volatile T referent; - - /** - * If non-null, the queue on which this reference will be enqueued - * when the referent is appropriately reachable. - * VM requirement: this field <em>must</em> be called "queue" - * and be a java.lang.ref.ReferenceQueue. - */ - volatile ReferenceQueue<? super T> queue; - - /** - * Used internally by java.lang.ref.ReferenceQueue. - * VM requirement: this field <em>must</em> be called "queueNext" - * and be a java.lang.ref.Reference. - */ - @SuppressWarnings("unchecked") - volatile Reference queueNext; - - /** - * Used internally by the VM. This field forms a circular and - * singly linked list of reference objects discovered by the - * garbage collector and awaiting processing by the reference - * queue thread. - * - * @hide - */ - public volatile Reference<?> pendingNext; - - /** - * Constructs a new instance of this class. - */ - Reference() { - } - - Reference(T r, ReferenceQueue<? super T> q) { - referent = r; - queue = q; - } - - /** - * Makes the referent {@code null}. This does not force the reference - * object to be enqueued. - */ - public void clear() { - referent = null; - } - - /** - * Adds an object to its reference queue. - * - * @return {@code true} if this call has caused the {@code Reference} to - * become enqueued, or {@code false} otherwise - * - * @hide - */ - public final synchronized boolean enqueueInternal() { - if (queue != null && queueNext == null) { - queue.enqueue(this); - queue = null; - return true; - } - return false; - } - - /** - * Forces the reference object to be enqueued if it has been associated with - * a queue. - * - * @return {@code true} if this call has caused the {@code Reference} to - * become enqueued, or {@code false} otherwise - */ - public boolean enqueue() { - return enqueueInternal(); - } - - /** - * Returns the referent of the reference object. - * - * @return the referent to which reference refers, or {@code null} if the - * object has been cleared. - */ - public T get() { - return referent; - } - - /** - * Checks whether the reference object has been enqueued. - * - * @return {@code true} if the {@code Reference} has been enqueued, {@code - * false} otherwise - */ - public boolean isEnqueued() { - return queueNext != null; - } - -} diff --git a/libdvm/src/main/java/java/lang/reflect/AccessibleObject.java b/libdvm/src/main/java/java/lang/reflect/AccessibleObject.java deleted file mode 100644 index f3d96af..0000000 --- a/libdvm/src/main/java/java/lang/reflect/AccessibleObject.java +++ /dev/null @@ -1,320 +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 java.lang.annotation.Annotation; -import java.util.Hashtable; -import org.apache.harmony.kernel.vm.StringUtils; - -/** - * {@code AccessibleObject} is the superclass of all member reflection classes - * (Field, Constructor, Method). AccessibleObject provides the ability to toggle - * a flag controlling access checks for these objects. By default, accessing a - * member (for example, setting a field or invoking a method) checks the - * validity of the access (for example, invoking a private method from outside - * the defining class is prohibited) and throws IllegalAccessException if the - * operation is not permitted. If the accessible flag is set to true, these - * checks are omitted. This allows privileged code, such as Java object - * serialization, object inspectors, and debuggers to have complete access to - * objects. - * - * @see Field - * @see Constructor - * @see Method - */ -public class AccessibleObject implements AnnotatedElement { - - /** - * If true, object is accessible, bypassing normal access checks - */ - boolean flag = false; - - // Holds a mapping from Java type names to native type codes. - static Hashtable<String, String> trans; - - static { - trans = new Hashtable<String, String>(9); - trans.put("byte", "B"); - trans.put("char", "C"); - trans.put("short", "S"); - trans.put("int", "I"); - trans.put("long", "J"); - trans.put("float", "F"); - trans.put("double", "D"); - trans.put("void", "V"); - trans.put("boolean", "Z"); - } - - /** - * Attempts to set the value of the accessible flag for all the objects in - * the array provided. Setting this - * flag to {@code false} will enable access checks, setting to {@code true} - * will disable them. - * - * @param objects - * the accessible objects - * @param flag - * the new value for the accessible flag - * - * @see #setAccessible(boolean) - */ - public static void setAccessible(AccessibleObject[] objects, boolean flag) { - for (AccessibleObject object : objects) { - object.flag = flag; - } - } - - /** - * Constructs a new {@code AccessibleObject} instance. {@code - * AccessibleObject} instances can only be constructed by the virtual - * machine. - */ - protected AccessibleObject() { - } - - /** - * Indicates whether this object is accessible without access checks being - * performed. Returns the accessible flag. - * - * @return {@code true} if this object is accessible without access - * checks, {@code false} otherwise - */ - public boolean isAccessible() { - return flag; - } - - /** - * Attempts to set the value of the accessible flag. Setting this flag to - * {@code false} will enable access checks, setting to {@code true} will - * disable them. - * - * @param flag - * the new value for the accessible flag - */ - public void setAccessible(boolean flag) { - this.flag = flag; - } - - public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) { - throw new UnsupportedOperationException(); - } - - public Annotation[] getDeclaredAnnotations() { - throw new UnsupportedOperationException(); - } - - public Annotation[] getAnnotations() { - // for all but Class, getAnnotations == getDeclaredAnnotations - return getDeclaredAnnotations(); - } - - public <T extends Annotation> T getAnnotation(Class<T> annotationType) { - throw new UnsupportedOperationException(); - } - - /** - * Returns the signature for a class. This is the kind of signature used - * internally by the JVM, with one-character codes representing the basic - * types. It is not suitable for printing. - * - * @param clazz - * the class for which a signature is required - * - * @return The signature as a string - */ - String getSignature(Class<?> clazz) { - String result = ""; - String nextType = clazz.getName(); - - if(trans.containsKey(nextType)) { - result = trans.get(nextType); - } else { - if(clazz.isArray()) { - result = "[" + getSignature(clazz.getComponentType()); - } else { - result = "L" + nextType + ";"; - } - } - return result; - } - - /** - * Returns a printable String consisting of the canonical names of the - * classes contained in an array. The form is that used in parameter and - * exception lists, that is, the class or type names are separated by - * commas. - * - * @param types - * the array of classes - * - * @return The String of names - */ - String toString(Class<?>[] types) { - StringBuilder result = new StringBuilder(); - - if (types.length != 0) { - appendTypeName(result, types[0]); - for (int i = 1; i < types.length; i++) { - result.append(','); - appendTypeName(result, types[i]); - } - } - - return result.toString(); - } - - /** - * Gets the Signature attribute for this instance. Returns {@code null} - * if not found. - */ - /*package*/ String getSignatureAttribute() { - /* - * Note: This method would have been declared abstract, but the - * standard API lists this class as concrete. - */ - throw new UnsupportedOperationException(); - } - - /** - * Retrieve the signature attribute from an arbitrary class. This is - * the same as Class.getSignatureAttribute(), but it can be used from - * the java.lang.reflect package. - */ - /*package*/ static String getClassSignatureAttribute(Class clazz) { - Object[] annotation = getClassSignatureAnnotation(clazz); - - if (annotation == null) { - return null; - } - - return StringUtils.combineStrings(annotation); - } - - /** - * Retrieve the signature annotation from an arbitrary class. This is - * the same as Class.getSignatureAttribute(), but it can be used from - * the java.lang.reflect package. - */ - private static native Object[] getClassSignatureAnnotation(Class clazz); - - /** - * Appends the best {@link #toString} name for {@code c} to {@code out}. - * This works around the fact that {@link Class#getName} is lousy for - * primitive arrays (it writes "[C" instead of "char[]") and {@link - * Class#getCanonicalName()} is lousy for nested classes (it uses a "." - * separator rather than a "$" separator). - */ - void appendTypeName(StringBuilder out, Class<?> c) { - int dimensions = 0; - while (c.isArray()) { - c = c.getComponentType(); - dimensions++; - } - out.append(c.getName()); - for (int d = 0; d < dimensions; d++) { - out.append("[]"); - } - } - - /** - * Appends names of the specified array classes to the buffer. The array - * elements may represent a simple type, a reference type or an array type. - * Output format: java.lang.Object[], java.io.File, void - * - * @param types array of classes to print the names - * @throws NullPointerException if any of the arguments is null - */ - void appendArrayGenericType(StringBuilder sb, Type[] types) { - if (types.length > 0) { - appendGenericType(sb, types[0]); - for (int i = 1; i < types.length; i++) { - sb.append(','); - appendGenericType(sb, types[i]); - } - } - } - - /** - * Appends the generic type representation to the buffer. - * - * @param sb buffer - * @param obj the generic type which representation should be appended to the buffer - * - * @throws NullPointerException if any of the arguments is null - */ - void appendGenericType(StringBuilder sb, Type obj) { - if (obj instanceof TypeVariable) { - sb.append(((TypeVariable)obj).getName()); - } else if (obj instanceof ParameterizedType) { - sb.append(obj.toString()); - } else if (obj instanceof GenericArrayType) { //XXX: is it a working branch? - Type simplified = ((GenericArrayType)obj).getGenericComponentType(); - appendGenericType(sb, simplified); - sb.append("[]"); - } else if (obj instanceof Class) { - Class c = ((Class<?>)obj); - if (c.isArray()){ - String as[] = c.getName().split("\\["); - int len = as.length-1; - if (as[len].length() > 1){ - sb.append(as[len].substring(1, as[len].length()-1)); - } else { - char ch = as[len].charAt(0); - if (ch == 'I') - sb.append("int"); - else if (ch == 'B') - sb.append("byte"); - else if (ch == 'J') - sb.append("long"); - else if (ch == 'F') - sb.append("float"); - else if (ch == 'D') - sb.append("double"); - else if (ch == 'S') - sb.append("short"); - else if (ch == 'C') - sb.append("char"); - else if (ch == 'Z') - sb.append("boolean"); - else if (ch == 'V') //XXX: is it a working branch? - sb.append("void"); - } - for (int i = 0; i < len; i++){ - sb.append("[]"); - } - } else { - sb.append(c.getName()); - } - } - } -} diff --git a/libdvm/src/main/java/java/lang/reflect/Constructor.java b/libdvm/src/main/java/java/lang/reflect/Constructor.java deleted file mode 100644 index acce44f..0000000 --- a/libdvm/src/main/java/java/lang/reflect/Constructor.java +++ /dev/null @@ -1,466 +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 java.lang.annotation.Annotation; -import libcore.util.EmptyArray; -import org.apache.harmony.kernel.vm.StringUtils; -import libcore.reflect.GenericSignatureParser; -import libcore.reflect.ListOfTypes; -import libcore.reflect.Types; - -/** - * This class represents a constructor. Information about the constructor can be - * accessed, and the constructor can be invoked dynamically. - * - * @param <T> the class that declares this constructor - */ -public final class Constructor<T> extends AccessibleObject implements GenericDeclaration, - Member { - - Class<T> declaringClass; - - Class<?>[] parameterTypes; - - Class<?>[] exceptionTypes; - - ListOfTypes genericExceptionTypes; - ListOfTypes genericParameterTypes; - TypeVariable<Constructor<T>>[] formalTypeParameters; - private volatile boolean genericTypesAreInitialized = false; - - private synchronized void initGenericTypes() { - if (!genericTypesAreInitialized) { - String signatureAttribute = getSignatureAttribute(); - GenericSignatureParser parser = new GenericSignatureParser( - declaringClass.getClassLoader()); - parser.parseForConstructor(this, signatureAttribute, exceptionTypes); - formalTypeParameters = parser.formalTypeParameters; - genericParameterTypes = parser.parameterTypes; - genericExceptionTypes = parser.exceptionTypes; - genericTypesAreInitialized = true; - } - } - - int slot; - - private int methodDexIndex; - - /** - * Prevent this class from being instantiated. - */ - private Constructor(){ - //do nothing - } - - /** - * Creates an instance of the class. Only called from native code, thus - * private. - * - * @param declaringClass - * the class this constructor object belongs to - * @param ptypes - * the parameter types of the constructor - * @param extypes - * the exception types of the constructor - * @param slot - * the slot of the constructor inside the VM class structure - */ - private Constructor(Class<T> declaringClass, Class<?>[] ptypes, Class<?>[] extypes, int slot, int methodDexIndex) { - this.declaringClass = declaringClass; - this.parameterTypes = ptypes; - this.exceptionTypes = extypes; // may be null - this.slot = slot; - this.methodDexIndex = methodDexIndex; - } - - /** @hide */ - public int getDexMethodIndex() { - return methodDexIndex; - } - - @Override /*package*/ String getSignatureAttribute() { - Object[] annotation = Method.getSignatureAnnotation(declaringClass, slot); - - if (annotation == null) { - return null; - } - - return StringUtils.combineStrings(annotation); - } - - public TypeVariable<Constructor<T>>[] getTypeParameters() { - initGenericTypes(); - return formalTypeParameters.clone(); - } - - /** - * Returns the string representation of the constructor's declaration, - * including the type parameters. - * - * @return the string representation of the constructor's declaration - */ - public String toGenericString() { - StringBuilder sb = new StringBuilder(80); - initGenericTypes(); - // append modifiers if any - int modifier = getModifiers(); - if (modifier != 0) { - sb.append(Modifier.toString(modifier & ~Modifier.VARARGS)).append(' '); - } - // append type parameters - if (formalTypeParameters != null && formalTypeParameters.length > 0) { - sb.append('<'); - for (int i = 0; i < formalTypeParameters.length; i++) { - appendGenericType(sb, formalTypeParameters[i]); - if (i < formalTypeParameters.length - 1) { - sb.append(","); - } - } - sb.append("> "); - } - // append constructor name - appendTypeName(sb, getDeclaringClass()); - // append parameters - sb.append('('); - appendArrayGenericType(sb, Types.getTypeArray(genericParameterTypes, false)); - sb.append(')'); - // append exceptions if any - Type[] genericExceptionTypeArray = Types.getTypeArray(genericExceptionTypes, false); - if (genericExceptionTypeArray.length > 0) { - sb.append(" throws "); - appendArrayGenericType(sb, genericExceptionTypeArray); - } - return sb.toString(); - } - - /** - * Returns the generic parameter types as an array of {@code Type} - * instances, in declaration order. If this constructor has no generic - * parameters, an empty array is returned. - * - * @return the parameter types - * - * @throws GenericSignatureFormatError - * if the generic constructor signature is invalid - * @throws TypeNotPresentException - * if any parameter type points to a missing type - * @throws MalformedParameterizedTypeException - * if any parameter type points to a type that cannot be - * instantiated for some reason - */ - public Type[] getGenericParameterTypes() { - initGenericTypes(); - return Types.getTypeArray(genericParameterTypes, true); - } - - /** - * Returns the exception types as an array of {@code Type} instances. If - * this constructor has no declared exceptions, an empty array will be - * returned. - * - * @return an array of generic exception types - * - * @throws GenericSignatureFormatError - * if the generic constructor signature is invalid - * @throws TypeNotPresentException - * if any exception type points to a missing type - * @throws MalformedParameterizedTypeException - * if any exception type points to a type that cannot be - * instantiated for some reason - */ - public Type[] getGenericExceptionTypes() { - initGenericTypes(); - return Types.getTypeArray(genericExceptionTypes, true); - } - - @Override - public Annotation[] getDeclaredAnnotations() { - return Method.getDeclaredAnnotations(declaringClass, slot); - } - - @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) { - if (annotationType == null) { - throw new NullPointerException("annotationType == null"); - } - return Method.getAnnotation(declaringClass, slot, annotationType); - } - - @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) { - if (annotationType == null) { - throw new NullPointerException("annotationType == null"); - } - return Method.isAnnotationPresent(declaringClass, slot, annotationType); - } - - /** - * Returns an array of arrays that represent the annotations of the formal - * parameters of this constructor. If there are no parameters on this - * constructor, then an empty array is returned. If there are no annotations - * set, then an array of empty arrays is returned. - * - * @return an array of arrays of {@code Annotation} instances - */ - public Annotation[][] getParameterAnnotations() { - Annotation[][] parameterAnnotations - = Method.getParameterAnnotations(declaringClass, slot); - if (parameterAnnotations.length == 0) { - return Method.noAnnotations(parameterTypes.length); - } - return parameterAnnotations; - } - - /** - * Indicates whether or not this constructor takes a variable number of - * arguments. - * - * @return {@code true} if a vararg is declare, otherwise - * {@code false} - */ - public boolean isVarArgs() { - int mods = Method.getMethodModifiers(declaringClass, slot); - return (mods & Modifier.VARARGS) != 0; - } - - /** - * Indicates whether or not this constructor is synthetic (artificially - * introduced by the compiler). - * - * @return {@code true} if this constructor is synthetic, {@code false} - * otherwise - */ - public boolean isSynthetic() { - int mods = Method.getMethodModifiers(declaringClass, slot); - return (mods & Modifier.SYNTHETIC) != 0; - } - - /** - * Indicates whether or not the specified {@code object} is equal to this - * constructor. To be equal, the specified object must be an instance - * of {@code Constructor} with the same declaring class and parameter types - * as this constructor. - * - * @param object - * the object to compare - * - * @return {@code true} if the specified object is equal to this - * constructor, {@code false} otherwise - * - * @see #hashCode - */ - @Override - public boolean equals(Object object) { - return object instanceof Constructor && toString().equals(object.toString()); - } - - /** - * Returns the class that declares this constructor. - * - * @return the declaring class - */ - public Class<T> getDeclaringClass() { - return declaringClass; - } - - /** - * Returns the exception types as an array of {@code Class} instances. If - * this constructor has no declared exceptions, an empty array will be - * returned. - * - * @return the declared exception classes - */ - public Class<?>[] getExceptionTypes() { - if (exceptionTypes == null) { - return EmptyArray.CLASS; - } - return exceptionTypes.clone(); - } - - /** - * Returns the modifiers for this constructor. The {@link Modifier} class - * should be used to decode the result. - * - * @return the modifiers for this constructor - * - * @see Modifier - */ - public int getModifiers() { - return Method.getMethodModifiers(declaringClass, slot); - } - - /** - * Returns the name of this constructor. - * - * @return the name of this constructor - */ - public String getName() { - return declaringClass.getName(); - } - - /** - * Returns an array of the {@code Class} objects associated with the - * parameter types of this constructor. If the constructor was declared with - * no parameters, an empty array will be returned. - * - * @return the parameter types - */ - public Class<?>[] getParameterTypes() { - return parameterTypes.clone(); - } - - /** - * Returns the constructor's signature in non-printable form. This is called - * (only) from IO native code and needed for deriving the serialVersionUID - * of the class - * - * @return the constructor's signature - */ - @SuppressWarnings("unused") - private String getSignature() { - StringBuilder result = new StringBuilder(); - - result.append('('); - for (int i = 0; i < parameterTypes.length; i++) { - result.append(getSignature(parameterTypes[i])); - } - result.append(")V"); - - return result.toString(); - } - - /** - * Returns an integer hash code for this constructor. Constructors which are - * equal return the same value for this method. The hash code for a - * Constructor is the hash code of the name of the declaring class. - * - * @return the hash code - * - * @see #equals - */ - @Override - public int hashCode() { - return declaringClass.getName().hashCode(); - } - - /** - * Returns a new instance of the declaring class, initialized by dynamically - * invoking the constructor represented by this {@code Constructor} object. - * This reproduces the effect of {@code new declaringClass(arg1, arg2, ... , - * argN)} This method performs the following: - * <ul> - * <li>A new instance of the declaring class is created. If the declaring - * class cannot be instantiated (i.e. abstract class, an interface, an array - * type, or a primitive type) then an InstantiationException is thrown.</li> - * <li>If this Constructor object is enforcing access control (see - * {@link AccessibleObject}) and this constructor is not accessible from the - * current context, an IllegalAccessException is thrown.</li> - * <li>If the number of arguments passed and the number of parameters do not - * match, an IllegalArgumentException is thrown.</li> - * <li>For each argument passed: - * <ul> - * <li>If the corresponding parameter type is a primitive type, the argument - * is unboxed. If the unboxing fails, an IllegalArgumentException is - * thrown.</li> - * <li>If the resulting argument cannot be converted to the parameter type - * via a widening conversion, an IllegalArgumentException is thrown.</li> - * </ul> - * <li>The constructor represented by this {@code Constructor} object is - * then invoked. If an exception is thrown during the invocation, it is - * caught and wrapped in an InvocationTargetException. This exception is - * then thrown. If the invocation completes normally, the newly initialized - * object is returned. - * </ul> - * - * @param args - * the arguments to the constructor - * - * @return the new, initialized, object - * - * @throws InstantiationException - * if the class cannot be instantiated - * @throws IllegalAccessException - * if this constructor is not accessible - * @throws IllegalArgumentException - * if an incorrect number of arguments are passed, or an - * argument could not be converted by a widening conversion - * @throws InvocationTargetException - * if an exception was thrown by the invoked constructor - * - * @see AccessibleObject - */ - public T newInstance(Object... args) throws InstantiationException, IllegalAccessException, - IllegalArgumentException, InvocationTargetException { - return constructNative (args, declaringClass, parameterTypes, slot, flag); - } - - private native T constructNative(Object[] args, Class<T> declaringClass, - Class<?>[] parameterTypes, int slot, - boolean noAccessCheck) throws InstantiationException, IllegalAccessException, - InvocationTargetException; - - /** - * Returns a string containing a concise, human-readable description of this - * constructor. The format of the string is: - * - * <ol> - * <li>modifiers (if any) - * <li>declaring class name - * <li>'(' - * <li>parameter types, separated by ',' (if any) - * <li>')' - * <li>'throws' plus exception types, separated by ',' (if any) - * </ol> - * - * For example: - * {@code public String(byte[],String) throws UnsupportedEncodingException} - * - * @return a printable representation for this constructor - */ - @Override - public String toString() { - StringBuilder result = new StringBuilder(Modifier.toString(getModifiers())); - - if (result.length() != 0) - result.append(' '); - result.append(declaringClass.getName()); - result.append("("); - result.append(toString(parameterTypes)); - result.append(")"); - if (exceptionTypes != null && exceptionTypes.length != 0) { - result.append(" throws "); - result.append(toString(exceptionTypes)); - } - - return result.toString(); - } -} diff --git a/libdvm/src/main/java/java/lang/reflect/Field.java b/libdvm/src/main/java/java/lang/reflect/Field.java deleted file mode 100644 index fa8e5e7..0000000 --- a/libdvm/src/main/java/java/lang/reflect/Field.java +++ /dev/null @@ -1,931 +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 java.lang.annotation.Annotation; -import java.util.Comparator; -import org.apache.harmony.kernel.vm.StringUtils; -import libcore.reflect.GenericSignatureParser; -import libcore.reflect.Types; - -/** - * This class represents a field. Information about the field can be accessed, - * and the field's value can be accessed dynamically. - */ -public final class Field extends AccessibleObject implements Member { - - /** - * Orders fields by their name and declaring class. - * - * @hide - */ - public static final Comparator<Field> ORDER_BY_NAME_AND_DECLARING_CLASS - = new Comparator<Field>() { - @Override public int compare(Field a, Field b) { - int comparison = a.name.compareTo(b.name); - if (comparison != 0) { - return comparison; - } - - return a.getDeclaringClass().getName().compareTo(b.getDeclaringClass().getName()); - } - }; - - private Class<?> declaringClass; - - private Class<?> type; - - private Type genericType; - - private volatile boolean genericTypesAreInitialized = false; - - private String name; - - private int slot; - - private final int fieldDexIndex; - - private static final char TYPE_BOOLEAN = 'Z'; - - private static final char TYPE_BYTE = 'B'; - - private static final char TYPE_CHAR = 'C'; - - private static final char TYPE_SHORT = 'S'; - - private static final char TYPE_INTEGER = 'I'; - - private static final char TYPE_FLOAT = 'F'; - - private static final char TYPE_LONG = 'J'; - - private static final char TYPE_DOUBLE = 'D'; - - private Field(Class<?> declaringClass, Class<?> type, String name, int slot, int fieldDexIndex) { - this.declaringClass = declaringClass; - this.type = type; - this.name = name; - this.slot = slot; - this.fieldDexIndex = fieldDexIndex; - } - - /** - * Returns the index of this field's ID in its dex file. - * @hide - */ - public int getDexFieldIndex() { - return fieldDexIndex; - } - - private synchronized void initGenericType() { - if (!genericTypesAreInitialized) { - String signatureAttribute = getSignatureAttribute(); - GenericSignatureParser parser = new GenericSignatureParser( - declaringClass.getClassLoader()); - parser.parseForField(this.declaringClass, signatureAttribute); - genericType = parser.fieldType; - if (genericType == null) { - genericType = getType(); - } - genericTypesAreInitialized = true; - } - } - - /** {@inheritDoc} */ - @Override - /* package */String getSignatureAttribute() { - Object[] annotation = getSignatureAnnotation(declaringClass, slot); - - if (annotation == null) { - return null; - } - - return StringUtils.combineStrings(annotation); - } - - /** - * Get the Signature annotation for this field. Returns null if not found. - */ - native private Object[] getSignatureAnnotation(Class declaringClass, int slot); - - /** - * Indicates whether or not this field is synthetic. - * - * @return {@code true} if this field is synthetic, {@code false} otherwise - */ - public boolean isSynthetic() { - int flags = getFieldModifiers(declaringClass, slot); - return (flags & Modifier.SYNTHETIC) != 0; - } - - /** - * Returns the string representation of this field, including the field's - * generic type. - * - * @return the string representation of this field - */ - public String toGenericString() { - StringBuilder sb = new StringBuilder(80); - // append modifiers if any - int modifier = getModifiers(); - if (modifier != 0) { - sb.append(Modifier.toString(modifier)).append(' '); - } - // append generic type - appendGenericType(sb, getGenericType()); - sb.append(' '); - // append full field name - sb.append(getDeclaringClass().getName()).append('.').append(getName()); - return sb.toString(); - } - - /** - * Indicates whether or not this field is an enumeration constant. - * - * @return {@code true} if this field is an enumeration constant, {@code - * false} otherwise - */ - public boolean isEnumConstant() { - int flags = getFieldModifiers(declaringClass, slot); - return (flags & Modifier.ENUM) != 0; - } - - /** - * Returns the generic type of this field. - * - * @return the generic type - * @throws GenericSignatureFormatError - * if the generic field signature is invalid - * @throws TypeNotPresentException - * if the generic type points to a missing type - * @throws MalformedParameterizedTypeException - * if the generic type points to a type that cannot be - * instantiated for some reason - */ - public Type getGenericType() { - initGenericType(); - return Types.getType(genericType); - } - - @Override public Annotation[] getDeclaredAnnotations() { - return getDeclaredAnnotations(declaringClass, slot); - } - private static native Annotation[] getDeclaredAnnotations(Class declaringClass, int slot); - - @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) { - if (annotationType == null) { - throw new NullPointerException("annotationType == null"); - } - return getAnnotation(declaringClass, slot, annotationType); - } - private static native <A extends Annotation> A getAnnotation( - Class<?> declaringClass, int slot, Class<A> annotationType); - - @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) { - if (annotationType == null) { - throw new NullPointerException("annotationType == null"); - } - return isAnnotationPresent(declaringClass, slot, annotationType); - } - private static native boolean isAnnotationPresent( - Class<?> declaringClass, int slot, Class<? extends Annotation> annotationType); - - /** - * Indicates whether or not the specified {@code object} is equal to this - * field. To be equal, the specified object must be an instance of - * {@code Field} with the same declaring class, type and name as this field. - * - * @param object - * the object to compare - * @return {@code true} if the specified object is equal to this method, - * {@code false} otherwise - * @see #hashCode - */ - @Override - public boolean equals(Object object) { - return object instanceof Field && toString().equals(object.toString()); - } - - /** - * Returns the value of the field in the specified object. This reproduces - * the effect of {@code object.fieldName} - * - * <p>If the type of this field is a primitive type, the field value is - * automatically boxed. - * - * <p>If this field is static, the object argument is ignored. - * Otherwise, if the object is null, a NullPointerException is thrown. If - * the object is not an instance of the declaring class of the method, an - * IllegalArgumentException is thrown. - * - * <p>If this Field object is enforcing access control (see AccessibleObject) - * and this field is not accessible from the current context, an - * IllegalAccessException is thrown. - * - * @param object - * the object to access - * @return the field value, possibly boxed - * @throws NullPointerException - * if the object is {@code null} and the field is non-static - * @throws IllegalArgumentException - * if the object is not compatible with the declaring class - * @throws IllegalAccessException - * if this field is not accessible - */ - public Object get(Object object) throws IllegalAccessException, IllegalArgumentException { - return getField(object, declaringClass, type, slot, flag); - } - - /** - * Returns the value of the field in the specified object as a {@code - * boolean}. This reproduces the effect of {@code object.fieldName} - * <p> - * If this field is static, the object argument is ignored. - * Otherwise, if the object is {@code null}, a NullPointerException is - * thrown. If the object is not an instance of the declaring class of the - * method, an IllegalArgumentException is thrown. - * <p> - * If this Field object is enforcing access control (see AccessibleObject) - * and this field is not accessible from the current context, an - * IllegalAccessException is thrown. - * - * @param object - * the object to access - * @return the field value - * @throws NullPointerException - * if the object is {@code null} and the field is non-static - * @throws IllegalArgumentException - * if the object is not compatible with the declaring class - * @throws IllegalAccessException - * if this field is not accessible - */ - public boolean getBoolean(Object object) throws IllegalAccessException, - IllegalArgumentException { - return getZField(object, declaringClass, type, slot, flag, TYPE_BOOLEAN); - } - - /** - * Returns the value of the field in the specified object as a {@code byte}. - * This reproduces the effect of {@code object.fieldName} - * <p> - * If this field is static, the object argument is ignored. - * Otherwise, if the object is {@code null}, a NullPointerException is - * thrown. If the object is not an instance of the declaring class of the - * method, an IllegalArgumentException is thrown. - * <p> - * If this Field object is enforcing access control (see AccessibleObject) - * and this field is not accessible from the current context, an - * IllegalAccessException is thrown. - * - * @param object - * the object to access - * @return the field value - * @throws NullPointerException - * if the object is {@code null} and the field is non-static - * @throws IllegalArgumentException - * if the object is not compatible with the declaring class - * @throws IllegalAccessException - * if this field is not accessible - */ - public byte getByte(Object object) throws IllegalAccessException, IllegalArgumentException { - return getBField(object, declaringClass, type, slot, flag, TYPE_BYTE); - } - - /** - * Returns the value of the field in the specified object as a {@code char}. - * This reproduces the effect of {@code object.fieldName} - * <p> - * If this field is static, the object argument is ignored. - * Otherwise, if the object is {@code null}, a NullPointerException is - * thrown. If the object is not an instance of the declaring class of the - * method, an IllegalArgumentException is thrown. - * <p> - * If this Field object is enforcing access control (see AccessibleObject) - * and this field is not accessible from the current context, an - * IllegalAccessException is thrown. - * - * @param object - * the object to access - * @return the field value - * @throws NullPointerException - * if the object is {@code null} and the field is non-static - * @throws IllegalArgumentException - * if the object is not compatible with the declaring class - * @throws IllegalAccessException - * if this field is not accessible - */ - public char getChar(Object object) throws IllegalAccessException, IllegalArgumentException { - return getCField(object, declaringClass, type, slot, flag, TYPE_CHAR); - } - - /** - * Returns the class that declares this field. - * - * @return the declaring class - */ - public Class<?> getDeclaringClass() { - return declaringClass; - } - - /** - * Returns the value of the field in the specified object as a {@code - * double}. This reproduces the effect of {@code object.fieldName} - * <p> - * If this field is static, the object argument is ignored. - * Otherwise, if the object is {@code null}, a NullPointerException is - * thrown. If the object is not an instance of the declaring class of the - * method, an IllegalArgumentException is thrown. - * <p> - * If this Field object is enforcing access control (see AccessibleObject) - * and this field is not accessible from the current context, an - * IllegalAccessException is thrown. - * - * @param object - * the object to access - * @return the field value - * @throws NullPointerException - * if the object is {@code null} and the field is non-static - * @throws IllegalArgumentException - * if the object is not compatible with the declaring class - * @throws IllegalAccessException - * if this field is not accessible - */ - public double getDouble(Object object) throws IllegalAccessException, IllegalArgumentException { - return getDField(object, declaringClass, type, slot, flag, TYPE_DOUBLE); - } - - /** - * Returns the value of the field in the specified object as a {@code float} - * . This reproduces the effect of {@code object.fieldName} - * <p> - * If this field is static, the object argument is ignored. - * Otherwise, if the object is {@code null}, a NullPointerException is - * thrown. If the object is not an instance of the declaring class of the - * method, an IllegalArgumentException is thrown. - * <p> - * If this Field object is enforcing access control (see AccessibleObject) - * and this field is not accessible from the current context, an - * IllegalAccessException is thrown. - * - * @param object - * the object to access - * @return the field value - * @throws NullPointerException - * if the object is {@code null} and the field is non-static - * @throws IllegalArgumentException - * if the object is not compatible with the declaring class - * @throws IllegalAccessException - * if this field is not accessible - */ - public float getFloat(Object object) throws IllegalAccessException, IllegalArgumentException { - return getFField(object, declaringClass, type, slot, flag, TYPE_FLOAT); - } - - /** - * Returns the value of the field in the specified object as an {@code int}. - * This reproduces the effect of {@code object.fieldName} - * <p> - * If this field is static, the object argument is ignored. - * Otherwise, if the object is {@code null}, a NullPointerException is - * thrown. If the object is not an instance of the declaring class of the - * method, an IllegalArgumentException is thrown. - * <p> - * If this Field object is enforcing access control (see AccessibleObject) - * and this field is not accessible from the current context, an - * IllegalAccessException is thrown. - * - * @param object - * the object to access - * @return the field value - * @throws NullPointerException - * if the object is {@code null} and the field is non-static - * @throws IllegalArgumentException - * if the object is not compatible with the declaring class - * @throws IllegalAccessException - * if this field is not accessible - */ - public int getInt(Object object) throws IllegalAccessException, IllegalArgumentException { - return getIField(object, declaringClass, type, slot, flag, TYPE_INTEGER); - } - - /** - * Returns the value of the field in the specified object as a {@code long}. - * This reproduces the effect of {@code object.fieldName} - * <p> - * If this field is static, the object argument is ignored. - * Otherwise, if the object is {@code null}, a NullPointerException is - * thrown. If the object is not an instance of the declaring class of the - * method, an IllegalArgumentException is thrown. - * <p> - * If this Field object is enforcing access control (see AccessibleObject) - * and this field is not accessible from the current context, an - * IllegalAccessException is thrown. - * - * @param object - * the object to access - * @return the field value - * @throws NullPointerException - * if the object is {@code null} and the field is non-static - * @throws IllegalArgumentException - * if the object is not compatible with the declaring class - * @throws IllegalAccessException - * if this field is not accessible - */ - public long getLong(Object object) throws IllegalAccessException, IllegalArgumentException { - return getJField(object, declaringClass, type, slot, flag, TYPE_LONG); - } - - /** - * Returns the modifiers for this field. The {@link Modifier} class should - * be used to decode the result. - * - * @return the modifiers for this field - * @see Modifier - */ - public int getModifiers() { - return getFieldModifiers(declaringClass, slot); - } - - private native int getFieldModifiers(Class<?> declaringClass, int slot); - - /** - * Returns the name of this field. - * - * @return the name of this field - */ - public String getName() { - return name; - } - - /** - * Returns the value of the field in the specified object as a {@code short} - * . This reproduces the effect of {@code object.fieldName} - * <p> - * If this field is static, the object argument is ignored. - * Otherwise, if the object is {@code null}, a NullPointerException is - * thrown. If the object is not an instance of the declaring class of the - * method, an IllegalArgumentException is thrown. - * <p> - * If this Field object is enforcing access control (see AccessibleObject) - * and this field is not accessible from the current context, an - * IllegalAccessException is thrown. - * - * @param object - * the object to access - * @return the field value - * @throws NullPointerException - * if the object is {@code null} and the field is non-static - * @throws IllegalArgumentException - * if the object is not compatible with the declaring class - * @throws IllegalAccessException - * if this field is not accessible - */ - public short getShort(Object object) throws IllegalAccessException, IllegalArgumentException { - return getSField(object, declaringClass, type, slot, flag, TYPE_SHORT); - } - - /** - * Returns the constructor's signature in non-printable form. This is called - * (only) from IO native code and needed for deriving the serialVersionUID - * of the class - * - * @return the constructor's signature. - */ - @SuppressWarnings("unused") - private String getSignature() { - return getSignature(type); - } - - /** - * Return the {@link Class} associated with the type of this field. - * - * @return the type of this field - */ - public Class<?> getType() { - return type; - } - - /** - * Returns an integer hash code for this field. Objects which are equal - * return the same value for this method. - * <p> - * The hash code for a Field is the exclusive-or combination of the hash - * code of the field's name and the hash code of the name of its declaring - * class. - * - * @return the hash code for this field - * @see #equals - */ - @Override - public int hashCode() { - return name.hashCode() ^ getDeclaringClass().getName().hashCode(); - } - - /** - * Sets the value of the field in the specified object to the value. This - * reproduces the effect of {@code object.fieldName = value} - * - * <p>If this field is static, the object argument is ignored. - * Otherwise, if the object is {@code null}, a NullPointerException is - * thrown. If the object is not an instance of the declaring class of the - * method, an IllegalArgumentException is thrown. - * - * <p>If this Field object is enforcing access control (see AccessibleObject) - * and this field is not accessible from the current context, an - * IllegalAccessException is thrown. - * - * <p>If the field type is a primitive type, the value is automatically - * unboxed. If the unboxing fails, an IllegalArgumentException is thrown. If - * the value cannot be converted to the field type via a widening - * conversion, an IllegalArgumentException is thrown. - * - * @param object - * the object to access - * @param value - * the new value - * @throws NullPointerException - * if the object is {@code null} and the field is non-static - * @throws IllegalArgumentException - * if the object is not compatible with the declaring class - * @throws IllegalAccessException - * if this field is not accessible - */ - public void set(Object object, Object value) throws IllegalAccessException, - IllegalArgumentException { - setField(object, declaringClass, type, slot, flag, value); - } - - /** - * Sets the value of the field in the specified object to the {@code - * boolean} value. This reproduces the effect of {@code object.fieldName = - * value} - * <p> - * If this field is static, the object argument is ignored. - * Otherwise, if the object is {@code null}, a NullPointerException is - * thrown. If the object is not an instance of the declaring class of the - * method, an IllegalArgumentException is thrown. - * <p> - * If this Field object is enforcing access control (see AccessibleObject) - * and this field is not accessible from the current context, an - * IllegalAccessException is thrown. - * <p> - * If the value cannot be converted to the field type via a widening - * conversion, an IllegalArgumentException is thrown. - * - * @param object - * the object to access - * @param value - * the new value - * @throws NullPointerException - * if the object is {@code null} and the field is non-static - * @throws IllegalArgumentException - * if the object is not compatible with the declaring class - * @throws IllegalAccessException - * if this field is not accessible - */ - public void setBoolean(Object object, boolean value) throws IllegalAccessException, - IllegalArgumentException { - setZField(object, declaringClass, type, slot, flag, TYPE_BOOLEAN, value); - } - - /** - * Sets the value of the field in the specified object to the {@code byte} - * value. This reproduces the effect of {@code object.fieldName = value} - * <p> - * If this field is static, the object argument is ignored. - * Otherwise, if the object is {@code null}, a NullPointerException is - * thrown. If the object is not an instance of the declaring class of the - * method, an IllegalArgumentException is thrown. - * <p> - * If this Field object is enforcing access control (see AccessibleObject) - * and this field is not accessible from the current context, an - * IllegalAccessException is thrown. - * <p> - * If the value cannot be converted to the field type via a widening - * conversion, an IllegalArgumentException is thrown. - * - * @param object - * the object to access - * @param value - * the new value - * @throws NullPointerException - * if the object is {@code null} and the field is non-static - * @throws IllegalArgumentException - * if the object is not compatible with the declaring class - * @throws IllegalAccessException - * if this field is not accessible - */ - public void setByte(Object object, byte value) throws IllegalAccessException, - IllegalArgumentException { - setBField(object, declaringClass, type, slot, flag, TYPE_BYTE, value); - } - - /** - * Sets the value of the field in the specified object to the {@code char} - * value. This reproduces the effect of {@code object.fieldName = value} - * <p> - * If this field is static, the object argument is ignored. - * Otherwise, if the object is {@code null}, a NullPointerException is - * thrown. If the object is not an instance of the declaring class of the - * method, an IllegalArgumentException is thrown. - * <p> - * If this Field object is enforcing access control (see AccessibleObject) - * and this field is not accessible from the current context, an - * IllegalAccessException is thrown. - * <p> - * If the value cannot be converted to the field type via a widening - * conversion, an IllegalArgumentException is thrown. - * - * @param object - * the object to access - * @param value - * the new value - * @throws NullPointerException - * if the object is {@code null} and the field is non-static - * @throws IllegalArgumentException - * if the object is not compatible with the declaring class - * @throws IllegalAccessException - * if this field is not accessible - */ - public void setChar(Object object, char value) throws IllegalAccessException, - IllegalArgumentException { - setCField(object, declaringClass, type, slot, flag, TYPE_CHAR, value); - } - - /** - * Sets the value of the field in the specified object to the {@code double} - * value. This reproduces the effect of {@code object.fieldName = value} - * <p> - * If this field is static, the object argument is ignored. - * Otherwise, if the object is {@code null}, a NullPointerException is - * thrown. If the object is not an instance of the declaring class of the - * method, an IllegalArgumentException is thrown. - * <p> - * If this Field object is enforcing access control (see AccessibleObject) - * and this field is not accessible from the current context, an - * IllegalAccessException is thrown. - * <p> - * If the value cannot be converted to the field type via a widening - * conversion, an IllegalArgumentException is thrown. - * - * @param object - * the object to access - * @param value - * the new value - * @throws NullPointerException - * if the object is {@code null} and the field is non-static - * @throws IllegalArgumentException - * if the object is not compatible with the declaring class - * @throws IllegalAccessException - * if this field is not accessible - */ - public void setDouble(Object object, double value) throws IllegalAccessException, - IllegalArgumentException { - setDField(object, declaringClass, type, slot, flag, TYPE_DOUBLE, value); - } - - /** - * Sets the value of the field in the specified object to the {@code float} - * value. This reproduces the effect of {@code object.fieldName = value} - * <p> - * If this field is static, the object argument is ignored. - * Otherwise, if the object is {@code null}, a NullPointerException is - * thrown. If the object is not an instance of the declaring class of the - * method, an IllegalArgumentException is thrown. - * <p> - * If this Field object is enforcing access control (see AccessibleObject) - * and this field is not accessible from the current context, an - * IllegalAccessException is thrown. - * <p> - * If the value cannot be converted to the field type via a widening - * conversion, an IllegalArgumentException is thrown. - * - * @param object - * the object to access - * @param value - * the new value - * @throws NullPointerException - * if the object is {@code null} and the field is non-static - * @throws IllegalArgumentException - * if the object is not compatible with the declaring class - * @throws IllegalAccessException - * if this field is not accessible - */ - public void setFloat(Object object, float value) throws IllegalAccessException, - IllegalArgumentException { - setFField(object, declaringClass, type, slot, flag, TYPE_FLOAT, value); - } - - /** - * Set the value of the field in the specified object to the {@code int} - * value. This reproduces the effect of {@code object.fieldName = value} - * <p> - * If this field is static, the object argument is ignored. - * Otherwise, if the object is {@code null}, a NullPointerException is - * thrown. If the object is not an instance of the declaring class of the - * method, an IllegalArgumentException is thrown. - * <p> - * If this Field object is enforcing access control (see AccessibleObject) - * and this field is not accessible from the current context, an - * IllegalAccessException is thrown. - * <p> - * If the value cannot be converted to the field type via a widening - * conversion, an IllegalArgumentException is thrown. - * - * @param object - * the object to access - * @param value - * the new value - * @throws NullPointerException - * if the object is {@code null} and the field is non-static - * @throws IllegalArgumentException - * if the object is not compatible with the declaring class - * @throws IllegalAccessException - * if this field is not accessible - */ - public void setInt(Object object, int value) throws IllegalAccessException, - IllegalArgumentException { - setIField(object, declaringClass, type, slot, flag, TYPE_INTEGER, value); - } - - /** - * Sets the value of the field in the specified object to the {@code long} - * value. This reproduces the effect of {@code object.fieldName = value} - * <p> - * If this field is static, the object argument is ignored. - * Otherwise, if the object is {@code null}, a NullPointerException is - * thrown. If the object is not an instance of the declaring class of the - * method, an IllegalArgumentException is thrown. - * <p> - * If this Field object is enforcing access control (see AccessibleObject) - * and this field is not accessible from the current context, an - * IllegalAccessException is thrown. - * <p> - * If the value cannot be converted to the field type via a widening - * conversion, an IllegalArgumentException is thrown. - * - * @param object - * the object to access - * @param value - * the new value - * @throws NullPointerException - * if the object is {@code null} and the field is non-static - * @throws IllegalArgumentException - * if the object is not compatible with the declaring class - * @throws IllegalAccessException - * if this field is not accessible - */ - public void setLong(Object object, long value) throws IllegalAccessException, - IllegalArgumentException { - setJField(object, declaringClass, type, slot, flag, TYPE_LONG, value); - } - - /** - * Sets the value of the field in the specified object to the {@code short} - * value. This reproduces the effect of {@code object.fieldName = value} - * <p> - * If this field is static, the object argument is ignored. - * Otherwise, if the object is {@code null}, a NullPointerException is - * thrown. If the object is not an instance of the declaring class of the - * method, an IllegalArgumentException is thrown. - * <p> - * If this Field object is enforcing access control (see AccessibleObject) - * and this field is not accessible from the current context, an - * IllegalAccessException is thrown. - * <p> - * If the value cannot be converted to the field type via a widening - * conversion, an IllegalArgumentException is thrown. - * - * @param object - * the object to access - * @param value - * the new value - * @throws NullPointerException - * if the object is {@code null} and the field is non-static - * @throws IllegalArgumentException - * if the object is not compatible with the declaring class - * @throws IllegalAccessException - * if this field is not accessible - */ - public void setShort(Object object, short value) throws IllegalAccessException, - IllegalArgumentException { - setSField(object, declaringClass, type, slot, flag, TYPE_SHORT, value); - } - - /** - * Returns a string containing a concise, human-readable description of this - * field. - * <p> - * The format of the string is: - * <ol> - * <li>modifiers (if any) - * <li>type - * <li>declaring class name - * <li>'.' - * <li>field name - * </ol> - * <p> - * For example: {@code public static java.io.InputStream - * java.lang.System.in} - * - * @return a printable representation for this field - */ - @Override - public String toString() { - StringBuilder result = new StringBuilder(Modifier.toString(getModifiers())); - if (result.length() != 0) { - result.append(' '); - } - appendTypeName(result, type); - result.append(' '); - appendTypeName(result, declaringClass); - result.append('.'); - result.append(name); - return result.toString(); - } - - private native Object getField(Object o, Class<?> declaringClass, Class<?> type, int slot, - boolean noAccessCheck) throws IllegalAccessException; - - private native double getDField(Object o, Class<?> declaringClass, Class<?> type, int slot, - boolean noAccessCheck, char descriptor) throws IllegalAccessException; - - private native int getIField(Object o, Class<?> declaringClass, Class<?> type, int slot, - boolean noAccessCheck, char descriptor) throws IllegalAccessException; - - private native long getJField(Object o, Class<?> declaringClass, Class<?> type, int slot, - boolean noAccessCheck, char descriptor) throws IllegalAccessException; - - private native boolean getZField(Object o, Class<?> declaringClass, Class<?> type, int slot, - boolean noAccessCheck, char descriptor) throws IllegalAccessException; - - private native float getFField(Object o, Class<?> declaringClass, Class<?> type, int slot, - boolean noAccessCheck, char descriptor) throws IllegalAccessException; - - private native char getCField(Object o, Class<?> declaringClass, Class<?> type, int slot, - boolean noAccessCheck, char descriptor) throws IllegalAccessException; - - private native short getSField(Object o, Class<?> declaringClass, Class<?> type, int slot, - boolean noAccessCheck, char descriptor) throws IllegalAccessException; - - private native byte getBField(Object o, Class<?> declaringClass, Class<?> type, int slot, - boolean noAccessCheck, char descriptor) throws IllegalAccessException; - - private native void setField(Object o, Class<?> declaringClass, Class<?> type, int slot, - boolean noAccessCheck, Object value) throws IllegalAccessException; - - private native void setDField(Object o, Class<?> declaringClass, Class<?> type, int slot, - boolean noAccessCheck, char descriptor, double v) throws IllegalAccessException; - - private native void setIField(Object o, Class<?> declaringClass, Class<?> type, int slot, - boolean noAccessCheck, char descriptor, int i) throws IllegalAccessException; - - private native void setJField(Object o, Class<?> declaringClass, Class<?> type, int slot, - boolean noAccessCheck, char descriptor, long j) throws IllegalAccessException; - - private native void setZField(Object o, Class<?> declaringClass, Class<?> type, int slot, - boolean noAccessCheck, char descriptor, boolean z) throws IllegalAccessException; - - private native void setFField(Object o, Class<?> declaringClass, Class<?> type, int slot, - boolean noAccessCheck, char descriptor, float f) throws IllegalAccessException; - - private native void setCField(Object o, Class<?> declaringClass, Class<?> type, int slot, - boolean noAccessCheck, char descriptor, char c) throws IllegalAccessException; - - private native void setSField(Object o, Class<?> declaringClass, Class<?> type, int slot, - boolean noAccessCheck, char descriptor, short s) throws IllegalAccessException; - - private native void setBField(Object o, Class<?> declaringClass, Class<?> type, int slot, - boolean noAccessCheck, char descriptor, byte b) throws IllegalAccessException; - -} diff --git a/libdvm/src/main/java/java/lang/reflect/Method.java b/libdvm/src/main/java/java/lang/reflect/Method.java deleted file mode 100644 index f8efbf4..0000000 --- a/libdvm/src/main/java/java/lang/reflect/Method.java +++ /dev/null @@ -1,587 +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 java.lang.annotation.Annotation; -import java.util.Arrays; -import java.util.Comparator; -import libcore.util.EmptyArray; -import org.apache.harmony.kernel.vm.StringUtils; -import libcore.reflect.GenericSignatureParser; -import libcore.reflect.ListOfTypes; -import libcore.reflect.Types; - -/** - * This class represents a method. Information about the method can be accessed, - * and the method can be invoked dynamically. - */ -public final class Method extends AccessibleObject implements GenericDeclaration, Member { - - /** - * Orders methods by their name, parameters and return type. - * - * @hide - */ - public static final Comparator<Method> ORDER_BY_SIGNATURE = new Comparator<Method>() { - public int compare(Method a, Method b) { - int comparison = a.name.compareTo(b.name); - if (comparison != 0) { - return comparison; - } - - Class<?>[] aParameters = a.parameterTypes; - Class<?>[] bParameters = b.parameterTypes; - int length = Math.min(aParameters.length, bParameters.length); - for (int i = 0; i < length; i++) { - comparison = aParameters[i].getName().compareTo(bParameters[i].getName()); - if (comparison != 0) { - return comparison; - } - } - - if (aParameters.length != bParameters.length) { - return aParameters.length - bParameters.length; - } - - // this is necessary for methods that have covariant return types. - return a.getReturnType().getName().compareTo(b.getReturnType().getName()); - } - }; - - private int slot; - - private final int methodDexIndex; - - private Class<?> declaringClass; - - private String name; - - private Class<?>[] parameterTypes; - - private Class<?>[] exceptionTypes; - - private Class<?> returnType; - - private ListOfTypes genericExceptionTypes; - private ListOfTypes genericParameterTypes; - private Type genericReturnType; - private TypeVariable<Method>[] formalTypeParameters; - private volatile boolean genericTypesAreInitialized = false; - - private synchronized void initGenericTypes() { - if (!genericTypesAreInitialized) { - String signatureAttribute = getSignatureAttribute(); - GenericSignatureParser parser = new GenericSignatureParser( - declaringClass.getClassLoader()); - parser.parseForMethod(this, signatureAttribute, exceptionTypes); - formalTypeParameters = parser.formalTypeParameters; - genericParameterTypes = parser.parameterTypes; - genericExceptionTypes = parser.exceptionTypes; - genericReturnType = parser.returnType; - genericTypesAreInitialized = true; - } - } - - private Method(Class<?> declaring, Class<?>[] paramTypes, Class<?>[] exceptTypes, Class<?> returnType, String name, int slot, int methodDexIndex) { - this.declaringClass = declaring; - this.name = name; - this.slot = slot; - this.parameterTypes = paramTypes; - this.exceptionTypes = exceptTypes; // may be null - this.returnType = returnType; - this.methodDexIndex = methodDexIndex; - } - - /** @hide */ - public int getDexMethodIndex() { - return methodDexIndex; - } - - public TypeVariable<Method>[] getTypeParameters() { - initGenericTypes(); - return formalTypeParameters.clone(); - } - - /** {@inheritDoc} */ - @Override /*package*/ String getSignatureAttribute() { - Object[] annotation = getSignatureAnnotation(declaringClass, slot); - - if (annotation == null) { - return null; - } - - return StringUtils.combineStrings(annotation); - } - - /** - * Returns the Signature annotation for this method. Returns {@code null} if - * not found. - */ - static native Object[] getSignatureAnnotation(Class declaringClass, int slot); - - /** - * Returns the string representation of the method's declaration, including - * the type parameters. - * - * @return the string representation of this method - */ - public String toGenericString() { - StringBuilder sb = new StringBuilder(80); - - initGenericTypes(); - - // append modifiers if any - int modifier = getModifiers(); - if (modifier != 0) { - sb.append(Modifier.toString(modifier & ~(Modifier.BRIDGE + - Modifier.VARARGS))).append(' '); - } - // append type parameters - if (formalTypeParameters != null && formalTypeParameters.length > 0) { - sb.append('<'); - for (int i = 0; i < formalTypeParameters.length; i++) { - appendGenericType(sb, formalTypeParameters[i]); - if (i < formalTypeParameters.length - 1) { - sb.append(","); - } - } - sb.append("> "); - } - // append return type - appendGenericType(sb, Types.getType(genericReturnType)); - sb.append(' '); - // append method name - appendTypeName(sb, getDeclaringClass()); - sb.append(".").append(getName()); - // append parameters - sb.append('('); - appendArrayGenericType(sb, Types.getTypeArray(genericParameterTypes, false)); - sb.append(')'); - // append exceptions if any - Type[] genericExceptionTypeArray = Types.getTypeArray(genericExceptionTypes, false); - if (genericExceptionTypeArray.length > 0) { - sb.append(" throws "); - appendArrayGenericType(sb, genericExceptionTypeArray); - } - return sb.toString(); - } - - /** - * Returns the parameter types as an array of {@code Type} instances, in - * declaration order. If this method has no parameters, an empty array is - * returned. - * - * @return the parameter types - * - * @throws GenericSignatureFormatError - * if the generic method signature is invalid - * @throws TypeNotPresentException - * if any parameter type points to a missing type - * @throws MalformedParameterizedTypeException - * if any parameter type points to a type that cannot be - * instantiated for some reason - */ - public Type[] getGenericParameterTypes() { - initGenericTypes(); - return Types.getTypeArray(genericParameterTypes, true); - } - - /** - * Returns the exception types as an array of {@code Type} instances. If - * this method has no declared exceptions, an empty array will be returned. - * - * @return an array of generic exception types - * - * @throws GenericSignatureFormatError - * if the generic method signature is invalid - * @throws TypeNotPresentException - * if any exception type points to a missing type - * @throws MalformedParameterizedTypeException - * if any exception type points to a type that cannot be - * instantiated for some reason - */ - public Type[] getGenericExceptionTypes() { - initGenericTypes(); - return Types.getTypeArray(genericExceptionTypes, true); - } - - /** - * Returns the return type of this method as a {@code Type} instance. - * - * @return the return type of this method - * - * @throws GenericSignatureFormatError - * if the generic method signature is invalid - * @throws TypeNotPresentException - * if the return type points to a missing type - * @throws MalformedParameterizedTypeException - * if the return type points to a type that cannot be - * instantiated for some reason - */ - public Type getGenericReturnType() { - initGenericTypes(); - return Types.getType(genericReturnType); - } - - @Override - public Annotation[] getDeclaredAnnotations() { - return getDeclaredAnnotations(declaringClass, slot); - } - static native Annotation[] getDeclaredAnnotations(Class<?> declaringClass, int slot); - - @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) { - if (annotationType == null) { - throw new NullPointerException("annotationType == null"); - } - return getAnnotation(declaringClass, slot, annotationType); - } - static native <A extends Annotation> A getAnnotation( - Class<?> declaringClass, int slot, Class<A> annotationType); - - @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) { - if (annotationType == null) { - throw new NullPointerException("annotationType == null"); - } - return isAnnotationPresent(declaringClass, slot, annotationType); - } - static native boolean isAnnotationPresent( - Class<?> declaringClass, int slot, Class<? extends Annotation> annotationType); - - private static final Annotation[] NO_ANNOTATIONS = new Annotation[0]; - - /** - * Creates an array of empty Annotation arrays. - */ - /*package*/ static Annotation[][] noAnnotations(int size) { - Annotation[][] annotations = new Annotation[size][]; - for (int i = 0; i < size; i++) { - annotations[i] = NO_ANNOTATIONS; - } - return annotations; - } - - /** - * Returns an array of arrays that represent the annotations of the formal - * parameters of this method. If there are no parameters on this method, - * then an empty array is returned. If there are no annotations set, then - * and array of empty arrays is returned. - * - * @return an array of arrays of {@code Annotation} instances - */ - public Annotation[][] getParameterAnnotations() { - Annotation[][] parameterAnnotations - = getParameterAnnotations(declaringClass, slot); - if (parameterAnnotations.length == 0) { - return noAnnotations(parameterTypes.length); - } - return parameterAnnotations; - } - - static native Annotation[][] getParameterAnnotations(Class declaringClass, int slot); - - /** - * Indicates whether or not this method takes a variable number argument. - * - * @return {@code true} if a vararg is declared, {@code false} otherwise - */ - public boolean isVarArgs() { - int modifiers = getMethodModifiers(declaringClass, slot); - return (modifiers & Modifier.VARARGS) != 0; - } - - /** - * Indicates whether or not this method is a bridge. - * - * @return {@code true} if this method is a bridge, {@code false} otherwise - */ - public boolean isBridge() { - int modifiers = getMethodModifiers(declaringClass, slot); - return (modifiers & Modifier.BRIDGE) != 0; - } - - /** - * Indicates whether or not this method is synthetic. - * - * @return {@code true} if this method is synthetic, {@code false} otherwise - */ - public boolean isSynthetic() { - int modifiers = getMethodModifiers(declaringClass, slot); - return (modifiers & Modifier.SYNTHETIC) != 0; - } - - /** - * Returns the default value for the annotation member represented by this - * method. - * - * @return the default value, or {@code null} if none - * - * @throws TypeNotPresentException - * if this annotation member is of type {@code Class} and no - * definition can be found - */ - public Object getDefaultValue() { - return getDefaultValue(declaringClass, slot); - } - native private Object getDefaultValue(Class declaringClass, int slot); - - /** - * Indicates whether or not the specified {@code object} is equal to this - * method. To be equal, the specified object must be an instance - * of {@code Method} with the same declaring class and parameter types - * as this method. - * - * @param object - * the object to compare - * - * @return {@code true} if the specified object is equal to this - * method, {@code false} otherwise - * - * @see #hashCode - */ - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (!(object instanceof Method)) { - return false; - } - Method rhs = (Method) object; - // We don't compare exceptionTypes because two methods - // can't differ only by their declared exceptions. - return declaringClass.equals(rhs.declaringClass) && - name.equals(rhs.name) && - getModifiers() == rhs.getModifiers() && - returnType.equals(rhs.returnType) && - Arrays.equals(parameterTypes, rhs.parameterTypes); - } - - /** - * Returns the class that declares this method. - * - * @return the declaring class - */ - public Class<?> getDeclaringClass() { - return declaringClass; - } - - /** - * Returns the exception types as an array of {@code Class} instances. If - * this method has no declared exceptions, an empty array is returned. - * - * @return the declared exception classes - */ - public Class<?>[] getExceptionTypes() { - if (exceptionTypes == null) { - return EmptyArray.CLASS; - } - return exceptionTypes.clone(); - } - - /** - * Returns the modifiers for this method. The {@link Modifier} class should - * be used to decode the result. - * - * @return the modifiers for this method - * - * @see Modifier - */ - public int getModifiers() { - return getMethodModifiers(declaringClass, slot); - } - - static native int getMethodModifiers(Class<?> declaringClass, int slot); - - /** - * Returns the name of the method represented by this {@code Method} - * instance. - * - * @return the name of this method - */ - public String getName() { - return name; - } - - /** - * Returns an array of {@code Class} objects associated with the parameter - * types of this method. If the method was declared with no parameters, an - * empty array will be returned. - * - * @return the parameter types - */ - public Class<?>[] getParameterTypes() { - return parameterTypes.clone(); - } - - /** - * Returns the {@code Class} associated with the return type of this - * method. - * - * @return the return type - */ - public Class<?> getReturnType() { - return returnType; - } - - /** - * Returns an integer hash code for this method. Objects which are equal - * return the same value for this method. The hash code for this Method is - * the hash code of the name of this method. - * - * @return hash code for this method - * - * @see #equals - */ - @Override - public int hashCode() { - return name.hashCode(); - } - - /** - * Returns the result of dynamically invoking this method. Equivalent to - * {@code receiver.methodName(arg1, arg2, ... , argN)}. - * - * <p>If the method is static, the receiver argument is ignored (and may be null). - * - * <p>If the method takes no arguments, you can pass {@code (Object[]) null} instead of - * allocating an empty array. - * - * <p>If you're calling a varargs method, you need to pass an {@code Object[]} for the - * varargs parameter: that conversion is usually done in {@code javac}, not the VM, and - * the reflection machinery does not do this for you. (It couldn't, because it would be - * ambiguous.) - * - * <p>Reflective method invocation follows the usual process for method lookup. - * - * <p>If an exception is thrown during the invocation it is caught and - * wrapped in an InvocationTargetException. This exception is then thrown. - * - * <p>If the invocation completes normally, the return value itself is - * returned. If the method is declared to return a primitive type, the - * return value is boxed. If the return type is void, null is returned. - * - * @param receiver - * the object on which to call this method (or null for static methods) - * @param args - * the arguments to the method - * @return the result - * - * @throws NullPointerException - * if {@code receiver == null} for a non-static method - * @throws IllegalAccessException - * if this method is not accessible (see {@link AccessibleObject}) - * @throws IllegalArgumentException - * if the number of arguments doesn't match the number of parameters, the receiver - * is incompatible with the declaring class, or an argument could not be unboxed - * or converted by a widening conversion to the corresponding parameter type - * @throws InvocationTargetException - * if an exception was thrown by the invoked method - */ - public Object invoke(Object receiver, Object... args) - throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - if (args == null) { - args = EmptyArray.OBJECT; - } - return invokeNative(receiver, args, declaringClass, parameterTypes, returnType, slot, flag); - } - - private native Object invokeNative(Object obj, Object[] args, Class<?> declaringClass, - Class<?>[] parameterTypes, Class<?> returnType, int slot, boolean noAccessCheck) - throws IllegalAccessException, IllegalArgumentException, - InvocationTargetException; - - /** - * Returns a string containing a concise, human-readable description of this - * method. The format of the string is: - * - * <ol> - * <li>modifiers (if any) - * <li>return type or 'void' - * <li>declaring class name - * <li>'(' - * <li>parameter types, separated by ',' (if any) - * <li>')' - * <li>'throws' plus exception types, separated by ',' (if any) - * </ol> - * - * For example: {@code public native Object - * java.lang.Method.invoke(Object,Object) throws - * IllegalAccessException,IllegalArgumentException - * ,InvocationTargetException} - * - * @return a printable representation for this method - */ - @Override - public String toString() { - StringBuilder result = new StringBuilder(Modifier.toString(getModifiers())); - - if (result.length() != 0) - result.append(' '); - result.append(returnType.getName()); - result.append(' '); - result.append(declaringClass.getName()); - result.append('.'); - result.append(name); - result.append("("); - result.append(toString(parameterTypes)); - result.append(")"); - if (exceptionTypes != null && exceptionTypes.length != 0) { - result.append(" throws "); - result.append(toString(exceptionTypes)); - } - - return result.toString(); - } - - /** - * Returns the constructor's signature in non-printable form. This is called - * (only) from IO native code and needed for deriving the serialVersionUID - * of the class - * - * @return The constructor's signature. - */ - @SuppressWarnings("unused") - private String getSignature() { - StringBuilder result = new StringBuilder(); - - result.append('('); - for (int i = 0; i < parameterTypes.length; i++) { - result.append(getSignature(parameterTypes[i])); - } - result.append(')'); - result.append(getSignature(returnType)); - - return result.toString(); - } - -} diff --git a/libdvm/src/main/java/java/lang/reflect/Proxy.java b/libdvm/src/main/java/java/lang/reflect/Proxy.java deleted file mode 100644 index 3b10887..0000000 --- a/libdvm/src/main/java/java/lang/reflect/Proxy.java +++ /dev/null @@ -1,278 +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. - */ - -package java.lang.reflect; - -import java.io.Serializable; -import java.lang.ref.WeakReference; -import java.util.HashMap; -import java.util.Map; -import java.util.WeakHashMap; - -/** - * {@code Proxy} defines methods for creating dynamic proxy classes and instances. - * A proxy class implements a declared set of interfaces and delegates method - * invocations to an {@code InvocationHandler}. - * - * @see InvocationHandler - * @since 1.3 - */ -public class Proxy implements Serializable { - - private static final long serialVersionUID = -2222568056686623797L; - - // maps class loaders to created classes by interface names - private static final Map<ClassLoader, Map<String, WeakReference<Class<?>>>> loaderCache = new WeakHashMap<ClassLoader, Map<String, WeakReference<Class<?>>>>(); - - // to find previously created types - private static final Map<Class<?>, String> proxyCache = new WeakHashMap<Class<?>, String>(); - - private static int NextClassNameIndex = 0; - - /** - * The invocation handler on which the method calls are dispatched. - */ - protected InvocationHandler h; - - @SuppressWarnings("unused") - private Proxy() { - } - - /** - * Constructs a new {@code Proxy} instance with the specified invocation - * handler. - * - * @param h - * the invocation handler for the newly created proxy - */ - protected Proxy(InvocationHandler h) { - this.h = h; - } - - /** - * Returns the dynamically built {@code Class} for the specified interfaces. - * Creates a new {@code Class} when necessary. The order of the interfaces - * is relevant. Invocations of this method with the same interfaces but - * different order result in different generated classes. The interfaces - * must be visible from the supplied class loader; no duplicates are - * permitted. All non-public interfaces must be defined in the same package. - * - * @param loader - * the class loader that will define the proxy class - * @param interfaces - * an array of {@code Class} objects, each one identifying an - * interface that will be implemented by the returned proxy - * class - * @return a proxy class that implements all of the interfaces referred to - * in the contents of {@code interfaces} - * @throws IllegalArgumentException - * if any of the interface restrictions are violated - * @throws NullPointerException - * if either {@code interfaces} or any of its elements are - * {@code null} - */ - public static Class<?> getProxyClass(ClassLoader loader, - Class<?>... interfaces) throws IllegalArgumentException { - // check that interfaces are a valid array of visible interfaces - if (interfaces == null) { - throw new NullPointerException("interfaces == null"); - } - String commonPackageName = null; - for (int i = 0, length = interfaces.length; i < length; i++) { - Class<?> next = interfaces[i]; - if (next == null) { - throw new NullPointerException("interfaces[" + i + "] == null"); - } - String name = next.getName(); - if (!next.isInterface()) { - throw new IllegalArgumentException(name + " is not an interface"); - } - if (loader != next.getClassLoader()) { - try { - if (next != Class.forName(name, false, loader)) { - throw new IllegalArgumentException(name + - " is not visible from class loader"); - } - } catch (ClassNotFoundException ex) { - throw new IllegalArgumentException(name + " is not visible from class loader"); - } - } - for (int j = i + 1; j < length; j++) { - if (next == interfaces[j]) { - throw new IllegalArgumentException(name + " appears more than once"); - } - } - if (!Modifier.isPublic(next.getModifiers())) { - int last = name.lastIndexOf('.'); - String p = last == -1 ? "" : name.substring(0, last); - if (commonPackageName == null) { - commonPackageName = p; - } else if (!commonPackageName.equals(p)) { - throw new IllegalArgumentException("non-public interfaces must be " + - "in the same package"); - } - } - } - - // search cache for matching proxy class using the class loader - synchronized (loaderCache) { - Map<String, WeakReference<Class<?>>> interfaceCache = loaderCache - .get(loader); - if (interfaceCache == null) { - loaderCache - .put( - loader, - (interfaceCache = new HashMap<String, WeakReference<Class<?>>>())); - } - - String interfaceKey = ""; - if (interfaces.length == 1) { - interfaceKey = interfaces[0].getName(); - } else { - StringBuilder names = new StringBuilder(); - for (int i = 0, length = interfaces.length; i < length; i++) { - names.append(interfaces[i].getName()); - names.append(' '); - } - interfaceKey = names.toString(); - } - - Class<?> newClass; - WeakReference<Class<?>> ref = interfaceCache.get(interfaceKey); - if (ref == null) { - String nextClassName = "$Proxy" + NextClassNameIndex++; - if (commonPackageName != null && commonPackageName.length() > 0) { - nextClassName = commonPackageName + "." + nextClassName; - } - if (loader == null) { - loader = ClassLoader.getSystemClassLoader(); - } - newClass = generateProxy(nextClassName.replace('.', '/'), interfaces, loader); - // Need a weak reference to the class so it can - // be unloaded if the class loader is discarded - interfaceCache.put(interfaceKey, new WeakReference<Class<?>>(newClass)); - synchronized (proxyCache) { - // the value is unused - proxyCache.put(newClass, ""); - } - } else { - newClass = ref.get(); - assert newClass != null : "\ninterfaceKey=\"" + interfaceKey + "\"" - + "\nloaderCache=\"" + loaderCache + "\"" - + "\nintfCache=\"" + interfaceCache + "\"" - + "\nproxyCache=\"" + proxyCache + "\""; - } - return newClass; - } - } - - /** - * Returns an instance of the dynamically built class for the specified - * interfaces. Method invocations on the returned instance are forwarded to - * the specified invocation handler. The interfaces must be visible from the - * supplied class loader; no duplicates are permitted. All non-public - * interfaces must be defined in the same package. - * - * @param loader - * the class loader that will define the proxy class - * @param interfaces - * an array of {@code Class} objects, each one identifying an - * interface that will be implemented by the returned proxy - * object - * @param h - * the invocation handler that handles the dispatched method - * invocations - * @return a new proxy object that delegates to the handler {@code h} - * @throws IllegalArgumentException - * if any of the interface restrictions are violated - * @throws NullPointerException - * if the interfaces or any of its elements are null - */ - public static Object newProxyInstance(ClassLoader loader, - Class<?>[] interfaces, InvocationHandler h) - throws IllegalArgumentException { - if (h == null) { - throw new NullPointerException("h == null"); - } - try { - return getProxyClass(loader, interfaces).getConstructor( - new Class<?>[] { InvocationHandler.class }).newInstance( - new Object[] { h }); - } catch (NoSuchMethodException ex) { - throw (InternalError) (new InternalError(ex.toString()) - .initCause(ex)); - } catch (IllegalAccessException ex) { - throw (InternalError) (new InternalError(ex.toString()) - .initCause(ex)); - } catch (InstantiationException ex) { - throw (InternalError) (new InternalError(ex.toString()) - .initCause(ex)); - } catch (InvocationTargetException ex) { - Throwable target = ex.getTargetException(); - throw (InternalError) (new InternalError(target.toString()) - .initCause(target)); - } - } - - /** - * Indicates whether or not the specified class is a dynamically generated - * proxy class. - * - * @param cl - * the class - * @return {@code true} if the class is a proxy class, {@code false} - * otherwise - * @throws NullPointerException - * if the class is {@code null} - */ - public static boolean isProxyClass(Class<?> cl) { - if (cl == null) { - throw new NullPointerException("cl == null"); - } - synchronized (proxyCache) { - return proxyCache.containsKey(cl); - } - } - - /** - * Returns the invocation handler of the specified proxy instance. - * - * @param proxy - * the proxy instance - * @return the invocation handler of the specified proxy instance - * @throws IllegalArgumentException - * if the supplied {@code proxy} is not a proxy object - */ - public static InvocationHandler getInvocationHandler(Object proxy) - throws IllegalArgumentException { - - if (isProxyClass(proxy.getClass())) { - return ((Proxy) proxy).h; - } - - throw new IllegalArgumentException("not a proxy instance"); - } - - native private static Class generateProxy(String name, Class[] interfaces, - ClassLoader loader); - - /* - * The VM clones this method's descriptor when generating a proxy class. - * There is no implementation. - */ - native private static void constructorPrototype(InvocationHandler h); -} diff --git a/libdvm/src/main/java/org/apache/harmony/kernel/vm/StringUtils.java b/libdvm/src/main/java/org/apache/harmony/kernel/vm/StringUtils.java deleted file mode 100644 index 01d0e30..0000000 --- a/libdvm/src/main/java/org/apache/harmony/kernel/vm/StringUtils.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 org.apache.harmony.kernel.vm; - -/** - * String utility functions. - */ -public final class StringUtils { - /** - * This class is uninstantiable. - */ - private StringUtils() { - // This space intentionally left blank. - } - - /** - * Combine a list of strings in an <code>Object[]</code> into a single - * string. - * - * @param list non-null; the strings to combine - * @return non-null; the combined form - */ - public static String combineStrings(Object[] list) { - int listLength = list.length; - - switch (listLength) { - case 0: { - return ""; - } - case 1: { - return (String) list[0]; - } - } - - int strLength = 0; - - for (int i = 0; i < listLength; i++) { - strLength += ((String) list[i]).length(); - } - - StringBuilder sb = new StringBuilder(strLength); - - for (int i = 0; i < listLength; i++) { - sb.append(list[i]); - } - - return sb.toString(); - } -} diff --git a/libdvm/src/main/java/sun/misc/Unsafe.java b/libdvm/src/main/java/sun/misc/Unsafe.java deleted file mode 100644 index 884340b..0000000 --- a/libdvm/src/main/java/sun/misc/Unsafe.java +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright (C) 2007 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 sun.misc; - -import dalvik.system.VMStack; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; - -/** - * The package name notwithstanding, this class is the quasi-standard - * way for Java code to gain access to and use functionality which, - * when unsupervised, would allow one to break the pointer/type safety - * of Java. - */ -public final class Unsafe { - /** Traditional dalvik name. */ - private static final Unsafe THE_ONE = new Unsafe(); - /** Traditional RI name. */ - private static final Unsafe theUnsafe = THE_ONE; - - /** - * This class is only privately instantiable. - */ - private Unsafe() {} - - /** - * Gets the unique instance of this class. This is only allowed in - * very limited situations. - */ - public static Unsafe getUnsafe() { - /* - * Only code on the bootclasspath is allowed to get at the - * Unsafe instance. - */ - ClassLoader calling = VMStack.getCallingClassLoader(); - if ((calling != null) && (calling != Unsafe.class.getClassLoader())) { - throw new SecurityException("Unsafe access denied"); - } - - return THE_ONE; - } - - /** - * Gets the raw byte offset from the start of an object's memory to - * the memory used to store the indicated instance field. - * - * @param field non-null; the field in question, which must be an - * instance field - * @return the offset to the field - */ - public long objectFieldOffset(Field field) { - if (Modifier.isStatic(field.getModifiers())) { - throw new IllegalArgumentException( - "valid for instance fields only"); - } - - return objectFieldOffset0(field); - } - - /** - * Helper for {@link #objectFieldOffset}, which does all the work, - * assuming the parameter is deemed valid. - * - * @param field non-null; the instance field - * @return the offset to the field - */ - private static native long objectFieldOffset0(Field field); - - /** - * Gets the offset from the start of an array object's memory to - * the memory used to store its initial (zeroeth) element. - * - * @param clazz non-null; class in question; must be an array class - * @return the offset to the initial element - */ - public int arrayBaseOffset(Class clazz) { - if (! clazz.isArray()) { - throw new IllegalArgumentException( - "valid for array classes only"); - } - - return arrayBaseOffset0(clazz); - } - - /** - * Helper for {@link #arrayBaseOffset}, which does all the work, - * assuming the parameter is deemed valid. - * - * @return the offset to the field - */ - private static native int arrayBaseOffset0(Class clazz); - - /** - * Gets the size of each element of the given array class. - * - * @param clazz non-null; class in question; must be an array class - * @return > 0; the size of each element of the array - */ - public int arrayIndexScale(Class clazz) { - if (! clazz.isArray()) { - throw new IllegalArgumentException( - "valid for array classes only"); - } - - return arrayIndexScale0(clazz); - } - - /** - * Helper for {@link #arrayIndexScale}, which does all the work, - * assuming the parameter is deemed valid. - * - * @return the offset to the field - */ - private static native int arrayIndexScale0(Class clazz); - - /** - * Performs a compare-and-set operation on an <code>int</code> - * field within the given object. - * - * @param obj non-null; object containing the field - * @param offset offset to the field within <code>obj</code> - * @param expectedValue expected value of the field - * @param newValue new value to store in the field if the contents are - * as expected - * @return <code>true</code> if the new value was in fact stored, and - * <code>false</code> if not - */ - public native boolean compareAndSwapInt(Object obj, long offset, - int expectedValue, int newValue); - - /** - * Performs a compare-and-set operation on a <code>long</code> - * field within the given object. - * - * @param obj non-null; object containing the field - * @param offset offset to the field within <code>obj</code> - * @param expectedValue expected value of the field - * @param newValue new value to store in the field if the contents are - * as expected - * @return <code>true</code> if the new value was in fact stored, and - * <code>false</code> if not - */ - public native boolean compareAndSwapLong(Object obj, long offset, - long expectedValue, long newValue); - - /** - * Performs a compare-and-set operation on an <code>Object</code> - * field (that is, a reference field) within the given object. - * - * @param obj non-null; object containing the field - * @param offset offset to the field within <code>obj</code> - * @param expectedValue expected value of the field - * @param newValue new value to store in the field if the contents are - * as expected - * @return <code>true</code> if the new value was in fact stored, and - * <code>false</code> if not - */ - public native boolean compareAndSwapObject(Object obj, long offset, - Object expectedValue, Object newValue); - - /** - * Gets an <code>int</code> field from the given object, - * using <code>volatile</code> semantics. - * - * @param obj non-null; object containing the field - * @param offset offset to the field within <code>obj</code> - * @return the retrieved value - */ - public native int getIntVolatile(Object obj, long offset); - - /** - * Stores an <code>int</code> field into the given object, - * using <code>volatile</code> semantics. - * - * @param obj non-null; object containing the field - * @param offset offset to the field within <code>obj</code> - * @param newValue the value to store - */ - public native void putIntVolatile(Object obj, long offset, int newValue); - - /** - * Gets a <code>long</code> field from the given object, - * using <code>volatile</code> semantics. - * - * @param obj non-null; object containing the field - * @param offset offset to the field within <code>obj</code> - * @return the retrieved value - */ - public native long getLongVolatile(Object obj, long offset); - - /** - * Stores a <code>long</code> field into the given object, - * using <code>volatile</code> semantics. - * - * @param obj non-null; object containing the field - * @param offset offset to the field within <code>obj</code> - * @param newValue the value to store - */ - public native void putLongVolatile(Object obj, long offset, long newValue); - - /** - * Gets an <code>Object</code> field from the given object, - * using <code>volatile</code> semantics. - * - * @param obj non-null; object containing the field - * @param offset offset to the field within <code>obj</code> - * @return the retrieved value - */ - public native Object getObjectVolatile(Object obj, long offset); - - /** - * Stores an <code>Object</code> field into the given object, - * using <code>volatile</code> semantics. - * - * @param obj non-null; object containing the field - * @param offset offset to the field within <code>obj</code> - * @param newValue the value to store - */ - public native void putObjectVolatile(Object obj, long offset, - Object newValue); - - /** - * Gets an <code>int</code> field from the given object. - * - * @param obj non-null; object containing the field - * @param offset offset to the field within <code>obj</code> - * @return the retrieved value - */ - public native int getInt(Object obj, long offset); - - /** - * Stores an <code>int</code> field into the given object. - * - * @param obj non-null; object containing the field - * @param offset offset to the field within <code>obj</code> - * @param newValue the value to store - */ - public native void putInt(Object obj, long offset, int newValue); - - /** - * Lazy set an int field. - */ - public native void putOrderedInt(Object obj, long offset, int newValue); - - /** - * Gets a <code>long</code> field from the given object. - * - * @param obj non-null; object containing the field - * @param offset offset to the field within <code>obj</code> - * @return the retrieved value - */ - public native long getLong(Object obj, long offset); - - /** - * Stores a <code>long</code> field into the given object. - * - * @param obj non-null; object containing the field - * @param offset offset to the field within <code>obj</code> - * @param newValue the value to store - */ - public native void putLong(Object obj, long offset, long newValue); - - /** - * Lazy set a long field. - */ - public native void putOrderedLong(Object obj, long offset, long newValue); - - /** - * Gets an <code>Object</code> field from the given object. - * - * @param obj non-null; object containing the field - * @param offset offset to the field within <code>obj</code> - * @return the retrieved value - */ - public native Object getObject(Object obj, long offset); - - /** - * Stores an <code>Object</code> field into the given object. - * - * @param obj non-null; object containing the field - * @param offset offset to the field within <code>obj</code> - * @param newValue the value to store - */ - public native void putObject(Object obj, long offset, Object newValue); - - /** - * Lazy set an object field. - */ - public native void putOrderedObject(Object obj, long offset, - Object newValue); - - /** - * Parks the calling thread for the specified amount of time, - * unless the "permit" for the thread is already available (due to - * a previous call to {@link #unpark}. This method may also return - * spuriously (that is, without the thread being told to unpark - * and without the indicated amount of time elapsing). - * - * <p>See {@link java.util.concurrent.locks.LockSupport} for more - * in-depth information of the behavior of this method.</p> - * - * @param absolute whether the given time value is absolute - * milliseconds-since-the-epoch (<code>true</code>) or relative - * nanoseconds-from-now (<code>false</code>) - * @param time the (absolute millis or relative nanos) time value - */ - public void park(boolean absolute, long time) { - if (absolute) { - Thread.currentThread().parkUntil(time); - } else { - Thread.currentThread().parkFor(time); - } - } - - /** - * Unparks the given object, which must be a {@link Thread}. - * - * <p>See {@link java.util.concurrent.locks.LockSupport} for more - * in-depth information of the behavior of this method.</p> - * - * @param obj non-null; the object to unpark - */ - public void unpark(Object obj) { - if (obj instanceof Thread) { - ((Thread) obj).unpark(); - } else { - throw new IllegalArgumentException("valid for Threads only"); - } - } - - /** - * Allocates an instance of the given class without running the constructor. - * The class' <clinit> will be run, if necessary. - */ - public native Object allocateInstance(Class<?> c); -} |