diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:03:55 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:03:55 -0800 |
commit | dd828f42a5c83b4270d4fbf6fce2da1878f1e84a (patch) | |
tree | fdd4b68fa1020f2b6426034c94823419a7236200 /dalvik | |
parent | fdb2704414a9ed92394ada0d1395e4db86889465 (diff) | |
download | libcore-dd828f42a5c83b4270d4fbf6fce2da1878f1e84a.zip libcore-dd828f42a5c83b4270d4fbf6fce2da1878f1e84a.tar.gz libcore-dd828f42a5c83b4270d4fbf6fce2da1878f1e84a.tar.bz2 |
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'dalvik')
27 files changed, 1362 insertions, 164 deletions
diff --git a/dalvik/src/main/java/dalvik/annotation/AndroidOnly.java b/dalvik/src/main/java/dalvik/annotation/AndroidOnly.java new file mode 100644 index 0000000..d55991b --- /dev/null +++ b/dalvik/src/main/java/dalvik/annotation/AndroidOnly.java @@ -0,0 +1,39 @@ +/* + * 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 dalvik.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marks a test-case as Android-only, that is, it should not be executed on + * other systems. + * + * @hide + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD, ElementType.TYPE }) +public @interface AndroidOnly { + + /** + * Plain text reason for adding this annotation. + */ + String value(); + +} diff --git a/dalvik/src/main/java/dalvik/annotation/BrokenTest.java b/dalvik/src/main/java/dalvik/annotation/BrokenTest.java new file mode 100644 index 0000000..961de41 --- /dev/null +++ b/dalvik/src/main/java/dalvik/annotation/BrokenTest.java @@ -0,0 +1,38 @@ +/* + * 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 dalvik.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marks a test case as broken. This means the test case should be fixed. + * + * @hide + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD }) +public @interface BrokenTest { + + /** + * Plain text reason for adding this annotation. + */ + String value(); + +} diff --git a/dalvik/src/main/java/dalvik/annotation/HostController.java b/dalvik/src/main/java/dalvik/annotation/HostController.java new file mode 100644 index 0000000..2ccc292 --- /dev/null +++ b/dalvik/src/main/java/dalvik/annotation/HostController.java @@ -0,0 +1,39 @@ +/* + * 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 dalvik.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Record the host side controller information for a test method, + * so that the CTS host can locate correspond host side unit while running it. + * {@hide pending API Council approval} + * + * @since Android 1.0 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD }) +public @interface HostController { + + /** + * The host controller method name. + */ + String name() default ""; +} diff --git a/dalvik/src/main/java/dalvik/annotation/KnownFailure.java b/dalvik/src/main/java/dalvik/annotation/KnownFailure.java new file mode 100644 index 0000000..f5040bb --- /dev/null +++ b/dalvik/src/main/java/dalvik/annotation/KnownFailure.java @@ -0,0 +1,40 @@ +/* + * 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 dalvik.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marks a test case as a known failure. This means the underlying + * implementation should be fixed. Seems to be similar to @code{@ToBeFixed}, so + * maybe the two can be merged at some point. + * + * @hide + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD }) +public @interface KnownFailure { + + /** + * Plain text reason for adding this annotation. + */ + String value(); + +} diff --git a/dalvik/src/main/java/dalvik/annotation/TestInfo.java b/dalvik/src/main/java/dalvik/annotation/TestInfo.java index e9c2128..876e0bf 100644 --- a/dalvik/src/main/java/dalvik/annotation/TestInfo.java +++ b/dalvik/src/main/java/dalvik/annotation/TestInfo.java @@ -43,6 +43,19 @@ public @interface TestInfo { String notes() default ""; /** + * Specifies the current level of coverage the test has. + */ + TestLevel level() default TestLevel.PARTIAL; + + /** + * Specifies the purpose (either if it is noteworth to mention such as if + * it is testing a specific parameter combination) or the covered test + * aspects (exceptions, normal cases, border edge cases, etc.) in + * case the level is Level.PARTIAL + */ + String purpose() default ""; + + /** * Specifies an array of target methods. */ TestTarget[] targets(); diff --git a/dalvik/src/main/java/dalvik/annotation/TestLevel.java b/dalvik/src/main/java/dalvik/annotation/TestLevel.java new file mode 100644 index 0000000..ff9ddb3 --- /dev/null +++ b/dalvik/src/main/java/dalvik/annotation/TestLevel.java @@ -0,0 +1,86 @@ +/* + * 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 dalvik.annotation; + +/** + * Defines an enumeration of possible states a test case can be in. + * + * @since Android 1.0 + * @hide + */ +public enum TestLevel { + + /** + * Indicates that a test method completely tests its target API method. + */ + COMPLETE, + + /** + * Indicates that a test method partially tests its target API method and + * that together with all other {@code PARTIAL_COMPLETE} tests for the same + * method it is sufficient. + */ + PARTIAL_COMPLETE, + + /** + * Just for compatibility purposes, will be removed later. + */ + PARTIAL_OK, + + /** + * Indicates that a test method partially tests its target API method. It + * needs a second review phase to find out if the sum of all partial tests + * is sufficient for completely testing the target API method. If yes, the + * level has to be changed to {@code PARTIAL_COMPLETE}. + */ + PARTIAL, + + /** + * Indicates that a test method is known to not completely test an API + * method but the missing test steps are too complex and costly to + * implement. This level is positioned somewhere between {@code PARTIAL} + * and {@code COMPLETE}. + */ + SUFFICIENT, + + /** + * Indicates that a test method provides additional testing for an API + * method for which there already exists one {@code COMPLETE} or a set of + * {@code PARTIAL_COMPLETE} tests. This level may also be used for test + * methods that test a concept which can not be directly attributed to + * the specification of an API method or class. + */ + ADDITIONAL, + + /** + * Indicates that there is nothing to test in an API method, for example if + * the specification states that a method does nothing. + */ + NOT_NECESSARY, + + /** + * Indicates that it is very hard or impossible to test an API method. + */ + NOT_FEASIBLE, + + /** + * Indicates that the tests is either insufficient or wrong. Something needs + * to be done about it. + */ + TODO, + +} diff --git a/dalvik/src/main/java/dalvik/annotation/TestTarget.java b/dalvik/src/main/java/dalvik/annotation/TestTarget.java index feefa05..7cbddca 100644 --- a/dalvik/src/main/java/dalvik/annotation/TestTarget.java +++ b/dalvik/src/main/java/dalvik/annotation/TestTarget.java @@ -25,6 +25,8 @@ import java.lang.annotation.Target; * Defines an annotation used be used within the TestInfo annotation. It * specifies a single method target for the test (but can be used multiple * times). + * + * @since Android 1.0 */ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.ANNOTATION_TYPE }) @@ -33,7 +35,19 @@ public @interface TestTarget { /** * Specifies the name of the method that is being tested. */ - String methodName(); + String methodName() default ""; + + /** + * Specifies the name of a concept being tested. Use this if + * {@code methodName} is not accurate enough. E.g. for + * {@link java.util.regex.Pattern#compile(String)} {@code methodName} is not + * sufficient since the String contains a pattern with its own syntax which + * has to be tested with different aspects. Areas concerned are e.g. JDBC + * (SELECT, INSERT, UPDATE, DELETE, ...), regex (character sets, + * operators,...), formatters (DecimalFormat, DateFormat, ChoiceFormat, + * ...), ... + */ + String conceptName() default ""; /** * Specifies the signature of the method that is being tested, in terms of diff --git a/dalvik/src/main/java/dalvik/annotation/TestTargetClass.java b/dalvik/src/main/java/dalvik/annotation/TestTargetClass.java index 59d104a..acbc1f1 100644 --- a/dalvik/src/main/java/dalvik/annotation/TestTargetClass.java +++ b/dalvik/src/main/java/dalvik/annotation/TestTargetClass.java @@ -21,11 +21,15 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import dalvik.annotation.TestTargetNew; + /** * Defines an annotation for test classes that allows to link them to the class * that is being tested. The current assumption is that the test are somewhat * organized according to the API classes they test. Might be too strict for * some cases. + * + * @since Android 1.0 */ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE }) @@ -36,4 +40,9 @@ public @interface TestTargetClass { */ Class<?> value(); -} + /** + * Option to specify untested methods for the class. + * @hide + */ + TestTargetNew[] untestedMethods() default {}; +}
\ No newline at end of file diff --git a/dalvik/src/main/java/dalvik/annotation/TestTargetNew.java b/dalvik/src/main/java/dalvik/annotation/TestTargetNew.java new file mode 100644 index 0000000..b8be0cb --- /dev/null +++ b/dalvik/src/main/java/dalvik/annotation/TestTargetNew.java @@ -0,0 +1,66 @@ +/* + * 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 dalvik.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Defines an annotation used be used within the TestInfo annotation. It + * specifies a single method target for the test (but can be used multiple + * times). + * + * @since Android 1.0 + * @hide + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) +public @interface TestTargetNew { + + /** + * Specifies the name of the API method that is being tested. This field + * may be left empty if the test target is a concept implemented in a + * class rather than a concrete API method. + */ + String method() default ""; + + /** + * Specifies the signature of the API method that is being tested, in terms + * of Java classes. + */ + Class<?>[] args() default {}; + + /** + * Specifies the class to which the tested method belongs. If this value is + * not provided, the class identified in @TestTargetClass is used by the + * test progress doclet. + */ + Class<?> clazz(); // default void.class; + + /** + * Specifies the level of coverage the tested API method has. + */ + TestLevel level(); + + /** + * Specifies noteworthy plain-text information about the test, for example + * if something is NOT covered by the test method. + */ + String notes() default ""; +} diff --git a/dalvik/src/main/java/dalvik/annotation/TestTargets.java b/dalvik/src/main/java/dalvik/annotation/TestTargets.java new file mode 100644 index 0000000..ead6149 --- /dev/null +++ b/dalvik/src/main/java/dalvik/annotation/TestTargets.java @@ -0,0 +1,43 @@ +/* + * 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 dalvik.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import dalvik.annotation.TestTargetNew; + +/** + * Defines an annotation for test classes that allows to link them to the class + * that is being tested. The current assumption is that the test are somewhat + * organized according to the API classes they test. Might be too strict for + * some cases. + * + * @since Android 1.0 + * @hide + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD }) +public @interface TestTargets { + + /** + * Specifies the API methods that are tested by the annotated test method. + */ + TestTargetNew[] value(); +}
\ No newline at end of file diff --git a/dalvik/src/main/java/dalvik/annotation/ToBeFixed.java b/dalvik/src/main/java/dalvik/annotation/ToBeFixed.java new file mode 100644 index 0000000..6985929 --- /dev/null +++ b/dalvik/src/main/java/dalvik/annotation/ToBeFixed.java @@ -0,0 +1,45 @@ +/* + * 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 dalvik.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Defines an annotation for test methods that indicate the test method + * need to be fixed in future. + * {@hide pending API Council approval} + * + * @since Android 1.0 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD }) +public @interface ToBeFixed { + + /** + * Specifies the related bug number on CTS bug tracking system. + */ + String bug() default ""; + + /** + * Specifies why this method need to be fixed. If we think it's a bug, explain + * the expectation and the actual result. + */ + String explanation() default ""; +} diff --git a/dalvik/src/main/java/dalvik/annotation/VirtualTestTarget.java b/dalvik/src/main/java/dalvik/annotation/VirtualTestTarget.java new file mode 100644 index 0000000..019e4b0 --- /dev/null +++ b/dalvik/src/main/java/dalvik/annotation/VirtualTestTarget.java @@ -0,0 +1,59 @@ +/* + * 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 dalvik.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation for "virtual" implementation classes. These are classes that have + * the following attributes: + * <ul> + * <li>they implement a public interface or are a concrete implementation of a + * public abstract class,</li> + * <li>they are not public,</li> + * <li>instances can only be retrieved through some kind of factory method.</li> + * </ul> + * <p> + * Example: {@code MessageDigest} is an abstract class. Concrete implementations + * of message digest algorithms such as MD5 and SHA-1 can only be retrieved + * through one of the static {@code getInstance} methods of + * {@code MessageDigest}, which accept the desired algorithm as a string + * parameter and return an implementation accordingly. + * </p> + * <p> + * Even though the concrete implementation class for a message digest algorithm + * is not known, we need to be able to indicate that such a class exists and + * that it must be tested. This is done by defining corresponding classes and + * annotating them with {@code @VirtualTestTarget}. This class can then be + * used in the {@code @TestTargetClass} annotation with which we annotate + * {@code TestCase} subclasses. + * + * @since Android 1.0 + * @hide + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE }) +public @interface VirtualTestTarget { + + /** + * Field for comments. + */ + String value() default ""; +}
\ No newline at end of file diff --git a/dalvik/src/main/java/dalvik/annotation/package.html b/dalvik/src/main/java/dalvik/annotation/package.html new file mode 100644 index 0000000..fc7cf07 --- /dev/null +++ b/dalvik/src/main/java/dalvik/annotation/package.html @@ -0,0 +1,9 @@ +<html> + <body> + <p> + Defines some annotations that are used within the Android system, either + for the core libraries or for testing purposes. + </p> + @since Android 1.0 + </body> +</html> diff --git a/dalvik/src/main/java/dalvik/bytecode/package.html b/dalvik/src/main/java/dalvik/bytecode/package.html new file mode 100644 index 0000000..1a6d7c4 --- /dev/null +++ b/dalvik/src/main/java/dalvik/bytecode/package.html @@ -0,0 +1,8 @@ +<html> + <body> + <p> + Provides classes surrounding the Dalvik bytecode. + </p> + @since Android 1.0 + </body> +</html> diff --git a/dalvik/src/main/java/dalvik/system/AllocationLimitError.java b/dalvik/src/main/java/dalvik/system/AllocationLimitError.java index 9747578..85f7de6 100644 --- a/dalvik/src/main/java/dalvik/system/AllocationLimitError.java +++ b/dalvik/src/main/java/dalvik/system/AllocationLimitError.java @@ -17,18 +17,22 @@ package dalvik.system; /** - * This is thrown when an allocation limit is exceeded. + * Is thrown when an allocation limit is exceeded. + * + * @since Android 1.0 */ public class AllocationLimitError extends VirtualMachineError { /** - * Initialize exception with default values. + * Creates a new exception instance and initializes it with default values. */ public AllocationLimitError() { super(); } /** - * Initialize exception with the supplied message string. + * Creates a new exception instance and initializes it with a given message. + * + * @param detailMessage the error message */ public AllocationLimitError(String detailMessage) { super(detailMessage); diff --git a/dalvik/src/main/java/dalvik/system/DexClassLoader.java b/dalvik/src/main/java/dalvik/system/DexClassLoader.java new file mode 100644 index 0000000..cb2f76d --- /dev/null +++ b/dalvik/src/main/java/dalvik/system/DexClassLoader.java @@ -0,0 +1,362 @@ +/* + * 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 dalvik.system; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.zip.ZipFile; +import java.net.MalformedURLException; + +import dalvik.system.DexFile; + +/** + * Provides a simple {@link ClassLoader} implementation that operates on a + * list of jar/apk files with classes.dex entries. The directory that + * holds the optimized form of the files is specified explicitly. This + * can be used to execute code not installed as part of an application. + * + * The best place to put the optimized DEX files is in app-specific + * storage, so that removal of the app will automatically remove the + * optimized DEX files. If other storage is used (e.g. /sdcard), the + * app may not have an opportunity to remove them. + */ +public class DexClassLoader extends ClassLoader { + + private static final boolean VERBOSE_DEBUG = false; + + /* constructor args, held for init */ + private final String mRawDexPath; + private final String mRawLibPath; + private final String mDexOutputPath; + + private boolean mInitialized; + + /* + * Parallel arrays for jar/apk files. + * + * (could stuff these into an object and have a single array; + * improves clarity but adds overhead) + */ + private File[] mFiles; // source file Files, for rsrc URLs + private ZipFile[] mZips; // source zip files, with resources + private DexFile[] mDexs; // opened, prepped DEX files + + /* + * Native library path. + */ + private String[] mLibPaths; + + + /** + * Creates a {@code DexClassLoader} that finds interpreted and native + * code. Interpreted classes are found in a set of DEX files contained + * in Jar or APK files. + * + * The path lists are separated using the character specified by + * the "path.separator" system property, which defaults to ":". + * + * @param dexPath + * the list of jar/apk files containing classes and resources + * @param dexOutputDir + * directory where optimized DEX files should be written + * @param libPath + * the list of directories containing native libraries; may be null + * @param parent + * the parent class loader + */ + public DexClassLoader(String dexPath, String dexOutputDir, String libPath, + ClassLoader parent) { + + super(parent); + + if (dexPath == null || dexOutputDir == null) + throw new NullPointerException(); + + mRawDexPath = dexPath; + mDexOutputPath = dexOutputDir; + mRawLibPath = libPath; + } + + /** + * Complete initialization on first use of the class loader. + */ + private void ensureInit() { + if (mInitialized) { + return; + } + + String[] dexPathList; + + mInitialized = true; + + dexPathList = mRawDexPath.split(":"); + int length = dexPathList.length; + + //System.out.println("DexClassLoader: " + dexPathList); + mFiles = new File[length]; + mZips = new ZipFile[length]; + mDexs = new DexFile[length]; + + /* open all Zip and DEX files up front */ + for (int i = 0; i < length; i++) { + System.out.println("My path is: " + dexPathList[i]); + File pathFile = new File(dexPathList[i]); + mFiles[i] = pathFile; + + if (pathFile.isFile()) { + try { + mZips[i] = new ZipFile(pathFile); + } catch (IOException ioex) { + // expecting IOException and ZipException + System.out.println("Failed opening '" + pathFile + + "': " + ioex); + //ioex.printStackTrace(); + } + + /* we need both DEX and Zip, because dex has no resources */ + try { + String outputName = + generateOutputName(dexPathList[i], mDexOutputPath); + mDexs[i] = DexFile.loadDex(dexPathList[i], outputName, 0); + } catch (IOException ioex) { + // might be a resource-only zip + System.out.println("Failed loadDex '" + pathFile + + "': " + ioex); + } + } else { + if (VERBOSE_DEBUG) + System.out.println("Not found: " + pathFile.getPath()); + } + } + + /* + * Prep for native library loading. + */ + String pathList = System.getProperty("java.library.path", "."); + String pathSep = System.getProperty("path.separator", ":"); + String fileSep = System.getProperty("file.separator", "/"); + + if (mRawLibPath != null) { + if (pathList.length() > 0) { + pathList += pathSep + mRawLibPath; + } + else { + pathList = mRawLibPath; + } + } + + mLibPaths = pathList.split(pathSep); + length = mLibPaths.length; + + // Add a '/' to the end so we don't have to do the property lookup + // and concatenation later. + for (int i = 0; i < length; i++) { + if (!mLibPaths[i].endsWith(fileSep)) + mLibPaths[i] += fileSep; + if (VERBOSE_DEBUG) + System.out.println("Native lib path " +i+ ": " + mLibPaths[i]); + } + } + + /** + * Convert a source path name and an output directory to an output + * file name. + */ + private static String generateOutputName(String sourcePathName, + String outputDir) { + + StringBuilder newStr = new StringBuilder(80); + + /* start with the output directory */ + newStr.append(outputDir); + if (!outputDir.endsWith("/")) + newStr.append("/"); + + /* get the filename component of the path */ + String sourceFileName; + int lastSlash = sourcePathName.lastIndexOf("/"); + if (lastSlash < 0) + sourceFileName = sourcePathName; + else + sourceFileName = sourcePathName.substring(lastSlash+1); + + /* replace ".jar", ".zip", whatever with ".odex" */ + int lastDot = sourceFileName.lastIndexOf("."); + if (lastDot < 0) + newStr.append(sourceFileName); + else + newStr.append(sourceFileName, 0, lastDot); + newStr.append(".odex"); + + if (VERBOSE_DEBUG) + System.out.println("Output file will be " + newStr.toString()); + return newStr.toString(); + } + + /** + * Finds a class. This method is called by {@code loadClass()} after the + * parent ClassLoader has failed to find a loaded class of the same name. + * + * @param name + * The name of the class to search for, in a human-readable form + * like "java.lang.String" or "java.net.URLClassLoader$3$1". + * @return the {@link Class} object representing the class + * @throws ClassNotFoundException + * if the class cannot be found + */ + @Override + protected Class<?> findClass(String name) throws ClassNotFoundException { + ensureInit(); + + if (VERBOSE_DEBUG) + System.out.println("DexClassLoader " + this + + ": findClass '" + name + "'"); + + byte[] data = null; + int length = mFiles.length; + + for (int i = 0; i < length; i++) { + if (VERBOSE_DEBUG) + System.out.println(" Now searching: " + mFiles[i].getPath()); + + if (mDexs[i] != null) { + String slashName = name.replace('.', '/'); + Class clazz = mDexs[i].loadClass(slashName, this); + if (clazz != null) { + if (VERBOSE_DEBUG) + System.out.println(" found"); + return clazz; + } + } + } + + throw new ClassNotFoundException(name + " in loader " + this); + } + + /** + * Finds a resource. This method is called by {@code getResource()} after + * the parent ClassLoader has failed to find a loaded resource of the same + * name. + * + * @param name + * The name of the resource to find + * @return the location of the resource as a URL, or {@code null} if the + * resource is not found. + */ + @Override + protected URL findResource(String name) { + ensureInit(); + + int length = mFiles.length; + + for (int i = 0; i < length; i++) { + File pathFile = mFiles[i]; + ZipFile zip = mZips[i]; + + if (zip.getEntry(name) != null) { + if (VERBOSE_DEBUG) + System.out.println(" found " + name + " in " + pathFile); + try { + // File.toURL() is compliant with RFC 1738 in always + // creating absolute path names. If we construct the + // URL by concatenating strings, we might end up with + // illegal URLs for relative names. + return new URL("jar:" + pathFile.toURL() + "!/" + name); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + } + + if (VERBOSE_DEBUG) + System.out.println(" resource " + name + " not found"); + + return null; + } + + /** + * Finds a native library. This method is called after the parent + * ClassLoader has failed to find a native library of the same name. + * + * @param libname + * The name of the library to find + * @return the complete path of the library, or {@code null} if the library + * is not found. + */ + @Override + protected String findLibrary(String libname) { + ensureInit(); + + String fileName = System.mapLibraryName(libname); + for (int i = 0; i < mLibPaths.length; i++) { + String pathName = mLibPaths[i] + fileName; + File test = new File(pathName); + + if (test.exists()) { + if (VERBOSE_DEBUG) + System.out.println(" found " + libname); + return pathName; + } + } + + if (VERBOSE_DEBUG) + System.out.println(" library " + libname + " not found"); + return null; + } + + /** + * Returns package information for the given package. Unfortunately, the + * DexClassLoader 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()</code> 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. + * + * @param name + * the name of the class + * @return the package information for the class, or {@code null} if there + * is not package information available for it + */ + @Override + protected Package getPackage(String name) { + if (name != null && !"".equals(name)) { + 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; + } +} + diff --git a/dalvik/src/main/java/dalvik/system/DexFile.java b/dalvik/src/main/java/dalvik/system/DexFile.java index 8fa1062..da51e45 100644 --- a/dalvik/src/main/java/dalvik/system/DexFile.java +++ b/dalvik/src/main/java/dalvik/system/DexFile.java @@ -24,80 +24,185 @@ import java.util.Enumeration; /** - * Manipulate DEX files. Similar in principle to java.util.zip.ZipFile. - * Used primarily by class loaders. - * - * We don't directly open and read the DEX file here. They're mapped read-only - * by the VM. + * Manipulates DEX files. The class is similar in principle to + * {@link java.util.zip.ZipFile}. It is used primarily by class loaders. + * <p> + * Note we don't directly open and read the DEX file here. They're memory-mapped + * read-only by the VM. + * + * @since Android 1.0 */ public final class DexFile { private final int mCookie; private String mFileName; /** - * Open a DEX file from a File object. + * Opens a DEX file from a given File object. This will usually be a ZIP/JAR + * file with a "classes.dex" inside. The method should not be used for files + * inside the Dalvik cache. + * + * @cts What will happen if we refer to the Dalvik cache? Should be either + * specified or throw an exception... + * + * @param file + * the File object referencing the actual DEX file + * + * @throws IOException + * if an I/O error occurs, such as the file not being found or + * access rights missing for opening it */ public DexFile(File file) throws IOException { this(file.getPath()); } /** - * Open a DEX file from a filename (preferrably a full path). - * - * This will usually be a Zip/Jar with a "classes.dex" inside. Do not - * specify the "dalvik-cache" version directly. + * Opens a DEX file from a given filename. This will usually be a ZIP/JAR + * file with a "classes.dex" inside. The method should not be used for files + * inside the Dalvik cache. + * + * @cts What will happen if we refer to the Dalvik cache? Should be either + * specified or throw an exception... + * + * @param fileName + * the filename of the DEX file + * + * @throws IOException + * if an I/O error occurs, such as the file not being found or + * access rights missing for opening it */ public DexFile(String fileName) throws IOException { String wantDex = System.getProperty("android.vm.dexfile", "false"); if (!wantDex.equals("true")) throw new UnsupportedOperationException("No dex in this VM"); - mCookie = openDexFile(fileName); + mCookie = openDexFile(fileName, null, 0); mFileName = fileName; //System.out.println("DEX FILE cookie is " + mCookie); } /** - * Get the name of the open file. + * Opens a DEX file from a given filename, using a specified file + * to hold the optimized data. + * + * @param sourceName + * Jar or APK file with "classes.dex". + * @param outputName + * File that will hold the optimized form of the DEX data. + * @param flags + * Enable optional features. + */ + private DexFile(String sourceName, String outputName, int flags) + throws IOException { + + String wantDex = System.getProperty("android.vm.dexfile", "false"); + if (!wantDex.equals("true")) + throw new UnsupportedOperationException("No dex in this VM"); + + mCookie = openDexFile(sourceName, outputName, flags); + mFileName = sourceName; + //System.out.println("DEX FILE cookie is " + mCookie); + } + + /** + * Open a DEX file, specifying the file in which the optimized DEX + * data should be written. If the optimized form exists and appears + * to be current, it will be used; if not, the VM will attempt to + * regenerate it. + * + * This is intended for use by applications that wish to download + * and execute DEX files outside the usual application installation + * mechanism. This function should not be called directly by an + * application; instead, use a class loader such as + * dalvik.system.DexClassLoader. + * + * @param sourcePathName + * Jar or APK file with "classes.dex". (May expand this to include + * "raw DEX" in the future.) + * @param outputPathName + * File that will hold the optimized form of the DEX data. + * @param flags + * Enable optional features. (Currently none defined.) + * @return + * A new or previously-opened DexFile. + * @throws IOException + * If unable to open the source or output file. + */ + static public DexFile loadDex(String sourcePathName, String outputPathName, + int flags) throws IOException { + + /* + * TODO: we may want to cache previously-opened DexFile objects. + * The cache would be synchronized with close(). This would help + * us avoid mapping the same DEX more than once when an app + * decided to open it multiple times. In practice this may not + * be a real issue. + */ + return new DexFile(sourcePathName, outputPathName, flags); + } + + /** + * Gets the name of the (already opened) DEX file. + * + * @return the file name */ public String getName() { return mFileName; } /** - * Close a DEX file. - * - * This may not be able to release any resources. If classes have - * been loaded, the underlying storage can't be discarded. + * Closes the DEX file. + * <p> + * This may not be able to release any resources. If classes have been + * loaded, the underlying storage can't be discarded. + * + * @throws IOException + * if an I/O error occurs during closing the file, which + * normally should not happen + * + * @cts Second sentence is a bit cryptic. */ public void close() throws IOException { closeDexFile(mCookie); } /** - * Load a class. Returns the class on success, or a null reference + * Loads a class. Returns the class on success, or a {@code null} reference * on failure. - * - * If you are not calling this from a class loader, this is most likely - * not going to do what you want. Use Class.forName() instead. - * - * "name" should look like "java/lang/String". - * - * I'm not throwing an exception if the class isn't found because I - * don't want to be throwing exceptions wildly every time we load a - * class that isn't in the first DEX file we look at. This method - * *will* throw exceptions for anything that isn't ClassNotFoundException. + * <p> + * If you are not calling this from a class loader, this is most likely not + * going to do what you want. Use {@link Class#forName(String)} instead. + * <p> + * The method does not throw {@link ClassNotFoundException} if the class + * isn't found because it isn't feasible to throw exceptions wildly every + * time a class is not found in the first DEX file we look at. It will + * throw exceptions for other failures, though. + * + * @param name + * the class name, which should look like "java/lang/String" + * + * @param loader + * the class loader that tries to load the class (in most cases + * the caller of the method + * + * @return the {@link Class} object representing the class, or {@code null} + * if the class cannot be loaded + * + * @cts Exception comment is a bit cryptic. What exception will be thrown? */ public Class loadClass(String name, ClassLoader loader) { return defineClass(name, loader, mCookie, null); //new ProtectionDomain(name) /*DEBUG ONLY*/); } + native private static Class defineClass(String name, ClassLoader loader, int cookie, ProtectionDomain pd); /** * Enumerate the names of the classes in this DEX file. + * + * @return an enumeration of names of classes contained in the DEX file, in + * the usual internal form (like "java/lang/String"). */ public Enumeration<String> entries() { return new DFEnum(this); @@ -128,7 +233,11 @@ public final class DexFile { native private static String[] getClassNameList(int cookie); /** - * GC helper. + * Called when the class is finalized. Makes sure the DEX file is closed. + * + * @throws IOException + * if an I/O error occurs during closing the file, which + * normally should not happen */ protected void finalize() throws IOException { close(); @@ -138,7 +247,12 @@ public final class DexFile { * Open a DEX file. The value returned is a magic VM cookie. On * failure, an IOException is thrown. */ - native private static int openDexFile(String fileName) throws IOException; + native private static int openDexFile(String sourceName, String outputName, + int flags) throws IOException; + + /* + * Close DEX file. + */ native private static void closeDexFile(int cookie); /** diff --git a/dalvik/src/main/java/dalvik/system/PathClassLoader.java b/dalvik/src/main/java/dalvik/system/PathClassLoader.java index 4dacf3f..94edfa1 100644 --- a/dalvik/src/main/java/dalvik/system/PathClassLoader.java +++ b/dalvik/src/main/java/dalvik/system/PathClassLoader.java @@ -23,6 +23,9 @@ import java.io.InputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.NoSuchElementException; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.net.MalformedURLException; @@ -30,9 +33,12 @@ import java.net.MalformedURLException; import dalvik.system.DexFile; /** - * Simple ClassLoader implementation. - * - * This loads classes from a colon-separated list. + * Provides a simple {@link ClassLoader} implementation that operates on a list + * of files and directories in the local file system, but does not attempt to + * load classes from the network. Android uses this class for its system class + * loader and for its application class loader(s). + * + * @since Android 1.0 */ public class PathClassLoader extends ClassLoader { @@ -48,22 +54,43 @@ public class PathClassLoader extends ClassLoader { private String[] mLibPaths; /** - * Create a ClassLoader that finds files in the specified path. + * Creates a {@code PathClassLoader} that operates on a given list of files + * and directories. This method is equivalent to calling + * {@link #PathClassLoader(String, String, ClassLoader) with a {@code null} + * value for the second argument (see description there). + * + * @param path + * the list of files and directories + * + * @param parent + * the parent class loader */ public PathClassLoader(String path, ClassLoader parent) { this(path, null, parent); } /** - * Create a ClassLoader that finds files in the specified path. - * - * The path is a colon-separated list of files and directories. For - * Dalvik, this is usually a list of .jar and .apk filenames. - * - * @param path A colon-separated class path. - * @param libPath A colon-separated list of directories where native - * libraries can be found. - * @param parent The parent class loader. + * Creates a {@code PathClassLoader} that operates on two given lists of + * files and directories. The entries of the first list should be one of the + * following: + * <ul> + * <li>Directories containing classes or resources. + * <li>JAR/ZIP/APK files, possibly containing a "classes.dex" file. + * <li>"classes.dex" files. + * </ul> + * The entries of the second list should be directories containing native + * library files. Both lists are separated using the character specified by + * the "path.separator" system property, which, on Android, defaults to ":". + * + * @param path + * the list of files and directories containing classes and + * resources + * + * @param libPath + * the list of directories containing native libraries + * + * @param parent + * the parent class loader */ public PathClassLoader(String path, String libPath, ClassLoader parent) { super(parent); @@ -148,14 +175,15 @@ public class PathClassLoader extends ClassLoader { } /** - * Find the class with the specified name. None of our ancestors were - * able to find it, so it's up to us now. - * - * "name" is a "binary name", e.g. "java.lang.String" or - * "java.net.URLClassLoader$3$1". - * - * This method will either return a valid Class object or throw an - * exception. Does not return null. + * Finds a class. This method is called by {@code loadClass()} after the + * parent ClassLoader has failed to find a loaded class of the same name. + * + * @param name + * The name of the class to search for, in a human-readable form + * like "java.lang.String" or "java.net.URLClassLoader$3$1". + * @return the {@link Class} object representing the class + * @throws ClassNotFoundException + * if the class cannot be found */ @Override protected Class<?> findClass(String name) throws ClassNotFoundException @@ -215,10 +243,17 @@ public class PathClassLoader extends ClassLoader { throw new ClassNotFoundException(name + " in loader " + this); } - /* - * Find a resource by name. This could be in a directory or in an - * archive. + /** + * Finds a resource. This method is called by {@code getResource()} after + * the parent ClassLoader has failed to find a loaded resource of the same + * name. + * + * @param name + * The name of the resource to find + * @return the location of the resource as a URL, or {@code null} if the + * resource is not found. */ + @Override protected URL findResource(String name) { ensureInit(); @@ -227,44 +262,75 @@ public class PathClassLoader extends ClassLoader { int length = mPaths.length; for (int i = 0; i < length; i++) { - File pathFile = mFiles[i]; - ZipFile zip = mZips[i]; - if (zip != null) { - if (isInArchive(zip, name)) { - //System.out.println(" found " + name + " in " + pathFile); - try { - // File.toURL() is compliant with RFC 1738 in always - // creating absolute path names. If we construct the - // URL by concatenating strings, we might end up with - // illegal URLs for relative names. - return new URL("jar:" + pathFile.toURL() + "!/" + name); - } - catch (MalformedURLException e) { - throw new RuntimeException(e); - } - } - } else if (pathFile.isDirectory()) { - File dataFile = new File(mPaths[i] + "/" + name); - if (dataFile.exists()) { - //System.out.println(" found resource " + name); - try { - // Same as archive case regarding URL construction. - return dataFile.toURL(); - } - catch (MalformedURLException e) { - throw new RuntimeException(e); - } - } - } else if (pathFile.isFile()) { - } else { - System.err.println("PathClassLoader: can't find '" - + mPaths[i] + "'"); + URL result = findResource(name, i); + if(result != null) { + return result; } } return null; } + /** + * Finds an enumeration of URLs for the resource with the specified name. + * + * @param resName + * the name of the resource to find. + * @return an enumeration of {@code URL} objects for the requested resource. + * @since Android 1.0 + */ + @Override + protected Enumeration<URL> findResources(String resName) { + ensureInit(); + + int length = mPaths.length; + ArrayList<URL> results = new ArrayList<URL>(); + + for (int i = 0; i < length; i++) { + URL result = findResource(resName, i); + if(result != null) { + results.add(result); + } + } + return new EnumerateListArray<URL>(results); + } + + private URL findResource(String name, int i) { + File pathFile = mFiles[i]; + ZipFile zip = mZips[i]; + if (zip != null) { + if (isInArchive(zip, name)) { + //System.out.println(" found " + name + " in " + pathFile); + try { + // File.toURL() is compliant with RFC 1738 in always + // creating absolute path names. If we construct the + // URL by concatenating strings, we might end up with + // illegal URLs for relative names. + return new URL("jar:" + pathFile.toURL() + "!/" + name); + } + catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + } else if (pathFile.isDirectory()) { + File dataFile = new File(mPaths[i] + "/" + name); + if (dataFile.exists()) { + //System.out.println(" found resource " + name); + try { + // Same as archive case regarding URL construction. + return dataFile.toURL(); + } + catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + } else if (pathFile.isFile()) { + } else { + System.err.println("PathClassLoader: can't find '" + + mPaths[i] + "'"); + } + return null; + } /* * Load the contents of a file from a file in a directory. @@ -345,11 +411,14 @@ public class PathClassLoader extends ClassLoader { return zip.getEntry(name) != null; } - /** - * Find a native library. - * - * Return the full pathname of the first appropriate-looking file - * we find. + /** + * Finds a native library. This method is called after the parent + * ClassLoader has failed to find a native library of the same name. + * + * @param libname + * The name of the library to find + * @return the complete path of the library, or {@code null} if the library + * is not found. */ protected String findLibrary(String libname) { ensureInit(); @@ -368,9 +437,9 @@ public class PathClassLoader extends ClassLoader { /** * Returns package information for the given package. Unfortunately, the - * PathClassLoader 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 + * PathClassLoader 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()</code> 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 @@ -382,6 +451,11 @@ public class PathClassLoader extends ClassLoader { * 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. + * + * @param name + * the name of the class + * @return the package information for the class, or {@code null} if there + * is not package information available for it */ @Override protected Package getPackage(String name) { @@ -400,4 +474,25 @@ public class PathClassLoader extends ClassLoader { return null; } + /* + * Create an Enumeration for an ArrayList. + */ + private static class EnumerateListArray<T> implements Enumeration<T> { + private final ArrayList mList; + private int i = 0; + + EnumerateListArray(ArrayList list) { + mList = list; + } + + public boolean hasMoreElements() { + return i < mList.size(); + } + + public T nextElement() { + if (i >= mList.size()) + throw new NoSuchElementException(); + return (T) mList.get(i++); + } + }; } diff --git a/dalvik/src/main/java/dalvik/system/PotentialDeadlockError.java b/dalvik/src/main/java/dalvik/system/PotentialDeadlockError.java index defa182..c85caee 100644 --- a/dalvik/src/main/java/dalvik/system/PotentialDeadlockError.java +++ b/dalvik/src/main/java/dalvik/system/PotentialDeadlockError.java @@ -17,18 +17,22 @@ package dalvik.system; /** - * This is thrown when the VM identifies a potential deadlock. + * Is thrown when the VM identifies a potential deadlock. + * + * @since Android 1.0 */ public class PotentialDeadlockError extends VirtualMachineError { /** - * Initialize exception with default values. + * Creates a new exception instance and initializes it with default values. */ public PotentialDeadlockError() { super(); } /** - * Initialize exception with the supplied message string. + * Creates a new exception instance and initializes it with a given message. + * + * @param detailMessage the error message */ public PotentialDeadlockError(String detailMessage) { super(detailMessage); diff --git a/dalvik/src/main/java/dalvik/system/StaleDexCacheError.java b/dalvik/src/main/java/dalvik/system/StaleDexCacheError.java index a124058..44a40a5 100644 --- a/dalvik/src/main/java/dalvik/system/StaleDexCacheError.java +++ b/dalvik/src/main/java/dalvik/system/StaleDexCacheError.java @@ -17,19 +17,21 @@ package dalvik.system; /** - * This is thrown when the VM determines that a dex file's cache - * is out of date, and that there is no way to recreate it. + * Is thrown when the VM determines that a DEX file's cache is out of date, and + * that there is no way to recreate it. */ public class StaleDexCacheError extends VirtualMachineError { /** - * Initialize exception with default values. + * Creates a new exception instance and initializes it with default values. */ public StaleDexCacheError() { super(); } /** - * Initialize exception with the supplied message string. + * Creates a new exception instance and initializes it with a given message. + * + * @param detailMessage the error message */ public StaleDexCacheError(String detailMessage) { super(detailMessage); diff --git a/dalvik/src/main/java/dalvik/system/TemporaryDirectory.java b/dalvik/src/main/java/dalvik/system/TemporaryDirectory.java index ae0ecb2..2f909ac 100644 --- a/dalvik/src/main/java/dalvik/system/TemporaryDirectory.java +++ b/dalvik/src/main/java/dalvik/system/TemporaryDirectory.java @@ -25,6 +25,8 @@ import java.util.logging.Logger; * call into this class with an appropriate base directory during its * startup, as a reasonably easy way to get the standard property * <code>java.io.tmpdir</code> to point at something useful. + * + * @since Android 1.0 */ public class TemporaryDirectory { /** system property name for the temporary directory */ diff --git a/dalvik/src/main/java/dalvik/system/TouchDex.java b/dalvik/src/main/java/dalvik/system/TouchDex.java index 5aedbf5..2dbc3ea 100644 --- a/dalvik/src/main/java/dalvik/system/TouchDex.java +++ b/dalvik/src/main/java/dalvik/system/TouchDex.java @@ -23,24 +23,30 @@ import java.io.File; import java.io.FilenameFilter; /** - * Induce optimization/verification of a set of DEX files. + * Induces optimization/verification of a set of DEX files. * * TODO: This class is public, so SystemServer can access it. This is NOT * the correct long-term solution; once we have a real installer and/or * dalvik-cache manager, this class should be removed. + * + * @cts See to-do about removing this class... + * + * @since Android 1.0 */ public class TouchDex { /** - * Fork a process, make sure the DEX files are prepped, and return + * Forks a process, makes sure the DEX files are prepared, and returns * when everything is finished. - * + * <p> * The filenames must be the same as will be used when the files are * actually opened, because the dalvik-cache filename is based upon - * this filename. (The absolute path to the jar/apk should work.) + * this filename. (The absolute path to the JAR/ZIP/APK should work.) * - * @param dexFiles Colon-separated list of DEX files. + * @param dexFiles a colon-separated list of DEX files. * @return zero on success + * + * @cts What about error cases? */ public static int start(String dexFiles) { return trampoline(dexFiles, System.getProperty("java.boot.class.path")); @@ -55,9 +61,9 @@ public class TouchDex { native private static int trampoline(String dexFiles, String bcp); /** - * We continue here in the child process. args[0] can be a colon-separated + * The entry point for the child process. args[0] can be a colon-separated * path list, or "-" to read from stdin. - * + * <p> * Alternatively, if we're invoked directly from the command line we * just start here (skipping the fork/exec stuff). * diff --git a/dalvik/src/main/java/dalvik/system/VMDebug.java b/dalvik/src/main/java/dalvik/system/VMDebug.java index 64a8321..9034ac1 100644 --- a/dalvik/src/main/java/dalvik/system/VMDebug.java +++ b/dalvik/src/main/java/dalvik/system/VMDebug.java @@ -17,14 +17,20 @@ package dalvik.system; /** - * VM-specific debug features. Though this class and many of its members - * are public, this class is meant to be wrapped in a more friendly way - * for use by application developers. On the Android platform, the + * Provides access to some VM-specific debug features. Though this class and + * many of its members are public, this class is meant to be wrapped in a more + * friendly way for use by application developers. On the Android platform, the * recommended way to access this functionality is through the class * <code>android.os.Debug</code>. + * + * @cts Please complete the spec. + * + * @since Android 1.0 */ public final class VMDebug { - /** default method trace data file name */ + /** + * Specifies the default method trace data file name. + */ static public final String DEFAULT_METHOD_TRACE_FILE_NAME = "/sdcard/dmtrace.trace"; /** @@ -88,13 +94,24 @@ public final class VMDebug { private VMDebug() {} /** - * Time, in msec, since the last debugger activity. -1 if debugger is - * not connected. + * Returns the time since the last known debugger activity. + * + * @return the time in milliseconds, or -1 if the debugger is not connected */ public static native long lastDebuggerActivity(); /** - * Determine if a debugger is currently attached. + * Determines if debugging is enabled in this VM. If debugging is not + * enabled, a debugger cannot be attached. + * + * @return true if debugging is enabled + */ + public static native boolean isDebuggingEnabled(); + + /** + * Determines if a debugger is currently attached. + * + * @return true if (and only if) a debugger is connected */ public static native boolean isDebuggerConnected(); @@ -134,30 +151,31 @@ public final class VMDebug { int bufferSize, int flags); /** - * Stop method tracing. + * Stops method tracing. */ public static native void stopMethodTracing(); /** - * Start sending Dalvik method trace info to the emulator. + * Starts sending Dalvik method trace info to the emulator. */ public static native void startEmulatorTracing(); /** - * Stop sending Dalvik method trace info to the emulator. + * Stops sending Dalvik method trace info to the emulator. */ public static native void stopEmulatorTracing(); /** - * Get an indication of thread CPU usage. The value returned - * indicates the amount of time that the current thread has spent - * executing code or waiting for certain types of I/O. - * - * The time is expressed in nanoseconds, and is only meaningful - * when compared to the result from an earlier call. Note that - * nanosecond resolution does not imply nanosecond accuracy. - * - * On system which don't support this operation, the call returns -1. + * Get an indication of thread CPU usage. The value returned indicates the + * amount of time that the current thread has spent executing code or + * waiting for certain types of I/O. + * <p> + * The time is expressed in nanoseconds, and is only meaningful when + * compared to the result from an earlier call. Note that nanosecond + * resolution does not imply nanosecond accuracy. + * + * @return the CPU usage. A value of -1 means the system does not support + * this feature. */ public static native long threadCpuTimeNanos(); @@ -171,23 +189,34 @@ public final class VMDebug { public static native void resetAllocCount(int kinds); /** - * Establish an object allocation limit in the current thread. Useful - * for catching regressions in code that is expected to operate - * without causing any allocations. - * - * Use -1 to disable the limit. - * - * Returns the previous limit. + * Establishes an object allocation limit in the current thread. Useful for + * catching regressions in code that is expected to operate without causing + * any allocations. The limit is valid from the return of this method until + * it is either changed or the thread terminates. + * + * @param limit + * the new limit. A value of 0 means not a single new object may + * be allocated. A value of -1 disables the limit. + * + * @return the previous limit, or -1 if no limit was set + * + * @see #setGlobalAllocationLimit(int) */ public static native int setAllocationLimit(int limit); /** - * Establish an object allocation limit for the entire VM. Very much - * like setAllocationLimit(). - * - * Use -1 to disable the limit. - * - * Returns the previous limit. + * Establishes an object allocation limit for the entire VM. Useful for + * catching regressions in code that is expected to operate without causing + * any allocations. The limit is valid from the return of this method until + * it is either changed or the thread terminates. + * + * @param limit + * the new limit. A value of 0 means not a single new object may + * be allocated. A value of -1 disables the limit. + * + * @return the previous limit, or -1 if no limit was set + * + * @see #setAllocationLimit(int) */ public static native int setGlobalAllocationLimit(int limit); @@ -200,12 +229,14 @@ public final class VMDebug { public static native void resetInstructionCount(); /** - * Dump a list of loaded class to the log file. + * Dumps a list of loaded class to the log file. */ public static native void printLoadedClasses(int flags); /** - * Get the number of loaded classes. + * Gets the number of loaded classes. + * + * @return the number of loaded classes */ public static native int getLoadedClassCount(); diff --git a/dalvik/src/main/java/dalvik/system/VMRuntime.java b/dalvik/src/main/java/dalvik/system/VMRuntime.java index 615d301..5d5e600 100644 --- a/dalvik/src/main/java/dalvik/system/VMRuntime.java +++ b/dalvik/src/main/java/dalvik/system/VMRuntime.java @@ -20,6 +20,8 @@ package dalvik.system; * 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. + * + * @since Android 1.0 */ public final class VMRuntime { @@ -173,6 +175,8 @@ public final class VMRuntime { /** * Returns the number of externally-allocated bytes being tracked by * trackExternalAllocation/Free(). + * + * @return the number of bytes */ public native long getExternalBytesAllocated(); } diff --git a/dalvik/src/main/java/dalvik/system/VMStack.java b/dalvik/src/main/java/dalvik/system/VMStack.java index 5d7a7d3..9330c68 100644 --- a/dalvik/src/main/java/dalvik/system/VMStack.java +++ b/dalvik/src/main/java/dalvik/system/VMStack.java @@ -17,32 +17,41 @@ package dalvik.system; /** - * VM-internal classes for examining a stack. + * Provides a limited interface to the Dalvik VM stack. This class is mostly + * used for implementing security checks. + * + * @since Android 1.0 */ public final class VMStack { /** - * Return the defining class loader of the caller's caller. + * 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(); /** - * Return the defining class loader of the caller's caller's caller. + * Returns the defining class loader of the caller's caller's caller. + * + * @return the requested class loader, or {@code null} if this is the + * bootstrap class loader. */ native public static ClassLoader getCallingClassLoader2(); /** - * Create an array of classes from the methods at the top of the stack. + * 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. If stopAtPrivileged is set, the last * element of the array will be the caller of the most-recent privileged * method. - * + * <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 expected to be identical to Harmony's VMStack.getClasses. * * @param maxDepth @@ -55,7 +64,7 @@ public final class VMStack { boolean stopAtPrivileged); /** - * Retrieve the stack trace from the specified thread. + * Retrieves the stack trace from the specified thread. * * @param t * thread of interest diff --git a/dalvik/src/main/java/dalvik/system/Zygote.java b/dalvik/src/main/java/dalvik/system/Zygote.java index 5c527ac..9d98bb2 100644 --- a/dalvik/src/main/java/dalvik/system/Zygote.java +++ b/dalvik/src/main/java/dalvik/system/Zygote.java @@ -1,14 +1,40 @@ -// Copyright 2006 The Android Open Source Project +/* + * Copyright (C) 2006 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; /** - * Interfaces for supporting the Dalvik "zygote" feature, which allows - * a VM instance to be partially initialized and then fork()'d from - * the partially initialized state. + * Provides access to the Dalvik "zygote" feature, which allows a VM instance to + * be partially initialized and then fork()'d from the partially initialized + * state. + * + * @since Android 1.0 */ - public class Zygote { + /* + * Bit values for "debugFlags" argument. The definitions are duplicated + * in the native code. + */ + /** enable debugging over JDWP */ + public static final int DEBUG_ENABLE_DEBUGGER = 1; + /** enable JNI checks */ + public static final int DEBUG_ENABLE_CHECKJNI = 1 << 1; + /** enable Java programming language "assert" statements */ + public static final int DEBUG_ENABLE_ASSERT = 1 << 2; + private Zygote() {} /** @@ -24,7 +50,7 @@ public class Zygote { /** * Forks a new VM instance. The current VM must have been started * with the -Xzygote flag. <b>NOTE: new instance keeps all - * root capabilities. The new process is expected to call capset()<b>. + * root capabilities. The new process is expected to call capset()</b>. * * @param uid the UNIX uid that the new process should setuid() to after * fork()ing and and before spawning any threads. @@ -32,7 +58,7 @@ public class Zygote { * fork()ing and and before spawning any threads. * @param gids null-ok; a list of UNIX gids that the new process should * setgroups() to after fork and before spawning any threads. - * @param enableDebugger true if JDWP should be enabled. + * @param debugFlags bit flags that enable debugging features. * @param rlimits null-ok an array of rlimit tuples, with the second * dimension having a length of 3 and representing * (resource, rlim_cur, rlim_max). These are set via the posix @@ -42,7 +68,18 @@ public class Zygote { * if this is the parent, or -1 on error. */ native public static int forkAndSpecialize(int uid, int gid, int[] gids, - boolean enableDebugger, int[][] rlimits); + int debugFlags, int[][] rlimits); + + /** + * Forks a new VM instance. + * @deprecated use {@link Zygote#forkAndSpecialize(int, int, int[], int, int[][])} + */ + @Deprecated + public static int forkAndSpecialize(int uid, int gid, int[] gids, + boolean enableDebugger, int[][] rlimits) { + int debugFlags = enableDebugger ? DEBUG_ENABLE_DEBUGGER : 0; + return forkAndSpecialize(uid, gid, gids, debugFlags, rlimits); + } /** * Special method to start the system server process. In addition to the @@ -56,7 +93,7 @@ public class Zygote { * fork()ing and and before spawning any threads. * @param gids null-ok; a list of UNIX gids that the new process should * setgroups() to after fork and before spawning any threads. - * @param enableDebugger true if JDWP should be enabled. + * @param debugFlags bit flags that enable debugging features. * @param rlimits null-ok an array of rlimit tuples, with the second * dimension having a length of 3 and representing * (resource, rlim_cur, rlim_max). These are set via the posix @@ -66,5 +103,17 @@ public class Zygote { * if this is the parent, or -1 on error. */ native public static int forkSystemServer(int uid, int gid, - int[] gids, boolean enableDebugger, int[][] rlimits); + int[] gids, int debugFlags, int[][] rlimits); + + /** + * Special method to start the system server process. + * @deprecated use {@link Zygote#forkSystemServer(int, int, int[], int, int[][])} + */ + @Deprecated + public static int forkSystemServer(int uid, int gid, int[] gids, + boolean enableDebugger, int[][] rlimits) { + int debugFlags = enableDebugger ? DEBUG_ENABLE_DEBUGGER : 0; + return forkAndSpecialize(uid, gid, gids, debugFlags, rlimits); + } } + diff --git a/dalvik/src/main/java/dalvik/system/package.html b/dalvik/src/main/java/dalvik/system/package.html new file mode 100644 index 0000000..215671c --- /dev/null +++ b/dalvik/src/main/java/dalvik/system/package.html @@ -0,0 +1,8 @@ +<html> + <body> + <p> + Provides utility and system information classes specific to the Dalvik VM. + </p> + @since Android 1.0 + </body> +</html> |