Merge "Removal of text/util spi classes and references"
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index ef7703e..43ea9d6 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -53,7 +53,7 @@
luni/src/main/java \
ojluni/src/main/resources/
test_resource_dirs := $(call all-core-resource-dirs,test)
-test_src_files := $(call all-test-java-files-under,dalvik dom harmony-tests json luni xml)
+test_src_files := $(call all-test-java-files-under,dalvik dalvik/test-rules dom harmony-tests json luni xml)
ojtest_src_files := $(call all-test-java-files-under,ojluni)
ifeq ($(EMMA_INSTRUMENT),true)
@@ -166,6 +166,24 @@
LOCAL_CORE_LIBRARY := true
include $(BUILD_JAVA_LIBRARY)
+# Build libcore test rules for target
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-java-files-under, dalvik/test-rules/src/main test-rules/src/main)
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_MODULE := core-test-rules
+LOCAL_JAVA_LIBRARIES := core-all core-junit
+LOCAL_STATIC_JAVA_LIBRARIES := junit4-target
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# Build libcore test rules for host
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-java-files-under, dalvik/test-rules/src/main test-rules/src/main)
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_MODULE := core-test-rules-hostdex
+LOCAL_JAVA_LIBRARIES := core-oj-hostdex core-libart-hostdex core-junit-hostdex
+LOCAL_STATIC_JAVA_LIBRARIES := junit4-target-hostdex
+include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
+
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(non_openjdk_java_files) $(android_icu4j_src_files)
LOCAL_JAVA_RESOURCE_DIRS := $(android_icu4j_resource_dirs)
@@ -189,8 +207,14 @@
LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
LOCAL_NO_STANDARD_LIBRARIES := true
LOCAL_JAVA_LIBRARIES := core-oj core-libart okhttp core-junit junit4-target bouncycastle mockito-target
-LOCAL_STATIC_JAVA_LIBRARIES := core-tests-support sqlite-jdbc mockwebserver nist-pkix-tests
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ core-test-rules \
+ core-tests-support \
+ mockwebserver \
+ nist-pkix-tests \
+ sqlite-jdbc
LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_ERROR_PRONE_FLAGS := -Xep:TryFailThrowable:ERROR
LOCAL_JAVA_LANGUAGE_VERSION := 1.8
LOCAL_MODULE := core-tests
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
@@ -329,14 +353,14 @@
LOCAL_CORE_LIBRARY := true
include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
-# Make the core-tests library.
+# Make the core-tests-hostdex library.
ifeq ($(LIBCORE_SKIP_TESTS),)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(test_src_files)
LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
LOCAL_NO_STANDARD_LIBRARIES := true
LOCAL_JAVA_LIBRARIES := core-oj-hostdex core-libart-hostdex okhttp-hostdex bouncycastle-hostdex core-junit-hostdex junit4-target-hostdex core-tests-support-hostdex mockito-api-hostdex
- LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc-host mockwebserver-host nist-pkix-tests-host
+ LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc-host mockwebserver-host nist-pkix-tests-host core-test-rules-hostdex
LOCAL_JAVACFLAGS := $(local_javac_flags)
LOCAL_MODULE_TAGS := optional
LOCAL_JAVA_LANGUAGE_VERSION := 1.8
diff --git a/benchmarks/src/benchmarks/regression/DateFormatBenchmark.java b/benchmarks/src/benchmarks/regression/DateFormatBenchmark.java
new file mode 100644
index 0000000..bd5bf1a
--- /dev/null
+++ b/benchmarks/src/benchmarks/regression/DateFormatBenchmark.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 Google Inc.
+ *
+ * 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 benchmarks.regression;
+
+import com.google.caliper.BeforeExperiment;
+
+import java.text.DateFormat;
+import java.util.Locale;
+
+public final class DateFormatBenchmark {
+
+ private Locale locale1;
+ private Locale locale2;
+ private Locale locale3;
+ private Locale locale4;
+
+ @BeforeExperiment
+ protected void setUp() throws Exception {
+ locale1 = Locale.TAIWAN;
+ locale2 = Locale.GERMANY;
+ locale3 = Locale.FRANCE;
+ locale4 = Locale.ITALY;
+ }
+
+ public void timeGetDateTimeInstance(int reps) throws Exception {
+ for (int i = 0; i < reps; ++i) {
+ DateFormat.getDateTimeInstance();
+ }
+ }
+
+ public void timeGetDateTimeInstance_multiple(int reps) throws Exception {
+ for (int i = 0; i < reps; ++i) {
+ DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale1);
+ DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale2);
+ DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale3);
+ DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale4);
+ }
+ }
+}
diff --git a/dalvik/src/main/java/dalvik/system/CloseGuard.java b/dalvik/src/main/java/dalvik/system/CloseGuard.java
index a45ffa1..e718ee7 100644
--- a/dalvik/src/main/java/dalvik/system/CloseGuard.java
+++ b/dalvik/src/main/java/dalvik/system/CloseGuard.java
@@ -118,6 +118,16 @@
private static volatile Reporter REPORTER = new DefaultReporter();
/**
+ * The default {@link Tracker}.
+ */
+ private static final DefaultTracker DEFAULT_TRACKER = new DefaultTracker();
+
+ /**
+ * Hook for customizing how CloseGuard issues are tracked.
+ */
+ private static volatile Tracker currentTracker = DEFAULT_TRACKER;
+
+ /**
* Returns a CloseGuard instance. If CloseGuard is enabled, {@code
* #open(String)} can be used to set up the instance to warn on
* failure to close. If CloseGuard is disabled, a non-null no-op
@@ -139,6 +149,13 @@
}
/**
+ * True if CloseGuard mechanism is enabled.
+ */
+ public static boolean isEnabled() {
+ return ENABLED;
+ }
+
+ /**
* Used to replace default Reporter used to warn of CloseGuard
* violations. Must be non-null.
*/
@@ -156,6 +173,32 @@
return REPORTER;
}
+ /**
+ * Sets the {@link Tracker} that is notified when resources are allocated and released.
+ *
+ * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
+ * MUST NOT be used for any other purposes.
+ *
+ * @throws NullPointerException if tracker is null
+ */
+ public static void setTracker(Tracker tracker) {
+ if (tracker == null) {
+ throw new NullPointerException("tracker == null");
+ }
+ currentTracker = tracker;
+ }
+
+ /**
+ * Returns {@link #setTracker(Tracker) last Tracker that was set}, or otherwise a default
+ * Tracker that does nothing.
+ *
+ * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
+ * MUST NOT be used for any other purposes.
+ */
+ public static Tracker getTracker() {
+ return currentTracker;
+ }
+
private CloseGuard() {}
/**
@@ -178,6 +221,7 @@
}
String message = "Explicit termination method '" + closer + "' not called";
allocationSite = new Throwable(message);
+ currentTracker.open(allocationSite);
}
private Throwable allocationSite;
@@ -187,6 +231,7 @@
* finalization.
*/
public void close() {
+ currentTracker.close(allocationSite);
allocationSite = null;
}
@@ -209,10 +254,35 @@
}
/**
+ * Interface to allow customization of tracking behaviour.
+ *
+ * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
+ * MUST NOT be used for any other purposes.
+ */
+ public interface Tracker {
+ void open(Throwable allocationSite);
+ void close(Throwable allocationSite);
+ }
+
+ /**
+ * Default tracker which does nothing special and simply leaves it up to the GC to detect a
+ * leak.
+ */
+ private static final class DefaultTracker implements Tracker {
+ @Override
+ public void open(Throwable allocationSite) {
+ }
+
+ @Override
+ public void close(Throwable allocationSite) {
+ }
+ }
+
+ /**
* Interface to allow customization of reporting behavior.
*/
- public static interface Reporter {
- public void report (String message, Throwable allocationSite);
+ public interface Reporter {
+ void report (String message, Throwable allocationSite);
}
/**
diff --git a/dalvik/src/test/java/dalvik/system/CloseGuardMonitor.java b/dalvik/src/test/java/dalvik/system/CloseGuardMonitor.java
deleted file mode 100644
index b5bf380..0000000
--- a/dalvik/src/test/java/dalvik/system/CloseGuardMonitor.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2014 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 dalvik.system.CloseGuard.Reporter;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.lang.ref.WeakReference;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-/**
- * Provides support for detecting issues found by {@link CloseGuard} from within tests.
- *
- * <p>This is a best effort as it relies on both {@link CloseGuard} being enabled and being able to
- * force a GC and finalization, none of which are directly controllable by this.
- *
- * <p>This is loaded using reflection by the AbstractResourceLeakageDetectorTestCase class as that
- * class needs to run on the reference implementation which does not have this class. It implements
- * {@link Runnable} because that is simpler than trying to manage a specialized interface.
- *
- * @hide
- */
-public class CloseGuardMonitor implements Runnable {
- /**
- * The {@link Reporter} instance used to receive warnings from {@link CloseGuard}.
- */
- private final Reporter closeGuardReporter;
-
- /**
- * The list of allocation sites that {@link CloseGuard} has reported as not being released.
- *
- * <p>Is thread safe as this will be called during finalization and so there are no guarantees
- * as to whether it will be called concurrently or not.
- */
- private final List<Throwable> closeGuardAllocationSites = new CopyOnWriteArrayList<>();
-
- /**
- * Default constructor required for reflection.
- */
- public CloseGuardMonitor() {
- System.logI("Creating CloseGuard monitor");
-
- // Save current reporter.
- closeGuardReporter = CloseGuard.getReporter();
-
- // Override the reporter with our own which collates the allocation sites.
- CloseGuard.setReporter(new Reporter() {
- @Override
- public void report(String message, Throwable allocationSite) {
- // Ignore message as it's always the same.
- closeGuardAllocationSites.add(allocationSite);
- }
- });
- }
-
- /**
- * Check to see whether any resources monitored by {@link CloseGuard} were not released before
- * they were garbage collected.
- */
- @Override
- public void run() {
- // Create a weak reference to an object so that we can detect when it is garbage collected.
- WeakReference<Object> reference = new WeakReference<>(new Object());
-
- try {
- // 'Force' a GC and finalize to cause CloseGuards to report warnings. Doesn't loop
- // forever as there are no guarantees that the following code does anything at all so
- // don't want a potential infinite loop.
- Runtime runtime = Runtime.getRuntime();
- for (int i = 0; i < 20; ++i) {
- runtime.gc();
- System.runFinalization();
- try {
- Thread.sleep(1);
- } catch (InterruptedException e) {
- throw new AssertionError(e);
- }
-
- // Check to see if the weak reference has been garbage collected.
- if (reference.get() == null) {
- System.logI("Sentry object has been freed so assuming CloseGuards have reported"
- + " any resource leakages");
- break;
- }
- }
- } finally {
- // Restore the reporter.
- CloseGuard.setReporter(closeGuardReporter);
- }
-
- if (!closeGuardAllocationSites.isEmpty()) {
- StringWriter writer = new StringWriter();
- PrintWriter printWriter = new PrintWriter(writer);
- int i = 0;
- for (Throwable allocationSite : closeGuardAllocationSites) {
- printWriter.print(++i);
- printWriter.print(") ");
- allocationSite.printStackTrace(printWriter);
- printWriter.println(" --------------------------------");
- }
- throw new AssertionError("Potential resource leakage detected:\n" + writer);
- }
- }
-}
diff --git a/dalvik/src/test/java/dalvik/system/CloseGuardTest.java b/dalvik/src/test/java/dalvik/system/CloseGuardTest.java
new file mode 100644
index 0000000..a1d1f42
--- /dev/null
+++ b/dalvik/src/test/java/dalvik/system/CloseGuardTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2016 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 org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * Tests {@link CloseGuard}.
+ */
+public class CloseGuardTest {
+
+ /**
+ * Resets the {@link CloseGuard#ENABLED} state back to the value it had when the test started.
+ */
+ @Rule
+ public TestRule rule = this::preserveEnabledState;
+
+ private Statement preserveEnabledState(final Statement base, Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ boolean oldEnabledState = CloseGuard.isEnabled();
+ try {
+ base.evaluate();
+ } finally {
+ CloseGuard.setEnabled(oldEnabledState);
+ }
+ }
+ };
+ }
+
+ @Test
+ public void testEnabled_NotOpen() throws Throwable {
+ CloseGuard.setEnabled(true);
+ ResourceOwner owner = new ResourceOwner();
+ assertUnreleasedResources(owner, 0);
+ }
+
+ @Test
+ public void testEnabled_OpenNotClosed() throws Throwable {
+ CloseGuard.setEnabled(true);
+ ResourceOwner owner = new ResourceOwner();
+ owner.open();
+ assertUnreleasedResources(owner, 1);
+ }
+
+ @Test
+ public void testEnabled_OpenThenClosed() throws Throwable {
+ CloseGuard.setEnabled(true);
+ ResourceOwner owner = new ResourceOwner();
+ owner.open();
+ owner.close();
+ assertUnreleasedResources(owner, 0);
+ }
+
+ @Test
+ public void testEnabledWhenCreated_DisabledWhenOpen() throws Throwable {
+ CloseGuard.setEnabled(true);
+ ResourceOwner owner = new ResourceOwner();
+ CloseGuard.setEnabled(false);
+ owner.open();
+
+ // Although the resource was not released it should not report it because CloseGuard was
+ // not enabled when the CloseGuard was opened.
+ assertUnreleasedResources(owner, 0);
+ }
+
+ @Test
+ public void testEnabledWhenOpened_DisabledWhenFinalized() throws Throwable {
+ CloseGuard.setEnabled(true);
+ ResourceOwner owner = new ResourceOwner();
+ owner.open();
+ CloseGuard.setEnabled(false);
+
+ // Although the resource was not released it should not report it because CloseGuard was
+ // not enabled when the CloseGuard was finalized.
+ assertUnreleasedResources(owner, 0);
+ }
+
+ @Test
+ public void testDisabled_NotOpen() throws Throwable {
+ CloseGuard.setEnabled(false);
+ ResourceOwner owner = new ResourceOwner();
+ assertUnreleasedResources(owner, 0);
+ }
+
+ @Test
+ public void testDisabled_OpenNotClosed() throws Throwable {
+ CloseGuard.setEnabled(false);
+ ResourceOwner owner = new ResourceOwner();
+ owner.open();
+ assertUnreleasedResources(owner, 0);
+ }
+
+ @Test
+ public void testDisabled_OpenThenClosed() throws Throwable {
+ CloseGuard.setEnabled(false);
+ ResourceOwner owner = new ResourceOwner();
+ owner.open();
+ owner.close();
+ assertUnreleasedResources(owner, 0);
+ }
+
+ @Test
+ public void testDisabledWhenCreated_EnabledWhenOpen() throws Throwable {
+ CloseGuard.setEnabled(false);
+ ResourceOwner owner = new ResourceOwner();
+ CloseGuard.setEnabled(true);
+ owner.open();
+
+ // Although the resource was not released it should not report it because CloseGuard was
+ // not enabled when the CloseGuard was created.
+ assertUnreleasedResources(owner, 0);
+ }
+
+ private void assertUnreleasedResources(ResourceOwner owner, int expectedCount)
+ throws Throwable {
+ try {
+ CloseGuardSupport.getFinalizerChecker().accept(owner, expectedCount);
+ } finally {
+ // Close the resource so that CloseGuard does not generate a warning for real when it
+ // is actually finalized.
+ owner.close();
+ }
+ }
+
+ /**
+ * A test user of {@link CloseGuard}.
+ */
+ private static class ResourceOwner {
+
+ private final CloseGuard closeGuard;
+
+ ResourceOwner() {
+ closeGuard = CloseGuard.get();
+ }
+
+ public void open() {
+ closeGuard.open("close");
+ }
+
+ public void close() {
+ closeGuard.close();
+ }
+
+ /**
+ * Make finalize public so that it can be tested directly without relying on garbage
+ * collection to trigger it.
+ */
+ @Override
+ public void finalize() throws Throwable {
+ closeGuard.warnIfOpen();
+ super.finalize();
+ }
+ }
+}
diff --git a/dalvik/test-rules/src/main/java/dalvik/system/CloseGuardSupport.java b/dalvik/test-rules/src/main/java/dalvik/system/CloseGuardSupport.java
new file mode 100644
index 0000000..7871795
--- /dev/null
+++ b/dalvik/test-rules/src/main/java/dalvik/system/CloseGuardSupport.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2016 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.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BiConsumer;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * Provides support for testing classes that use {@link CloseGuard} in order to detect resource
+ * leakages.
+ *
+ * <p>This class should not be used directly by tests as that will prevent them from being
+ * compilable and testable on OpenJDK platform. Instead they should use
+ * {@code libcore.junit.util.ResourceLeakageDetector} which accesses the capabilities of this using
+ * reflection and if it cannot find it (because it is running on OpenJDK) then it will just skip
+ * leakage detection.
+ *
+ * <p>This provides two entry points that are accessed reflectively:
+ * <ul>
+ * <li>
+ * <p>The {@link #getRule()} method. This returns a {@link TestRule} that will fail a test if it
+ * detects any resources that were allocated during the test but were not released.
+ *
+ * <p>This only tracks resources that were allocated on the test thread, although it does not care
+ * what thread they were released on. This avoids flaky false positives where a background thread
+ * allocates a resource during a test but releases it after the test.
+ *
+ * <p>It is still possible to have a false positive in the case where the test causes a caching
+ * mechanism to open a resource and hold it open past the end of the test. In that case if there is
+ * no way to clear the cached data then it should be relatively simple to move the code that invokes
+ * the caching mechanism to outside the scope of this rule. i.e.
+ *
+ * <pre>{@code
+ * @Rule
+ * public final TestRule ruleChain = org.junit.rules.RuleChain
+ * .outerRule(new ...invoke caching mechanism...)
+ * .around(CloseGuardSupport.getRule());
+ * }</pre>
+ * </li>
+ * <li>
+ * <p>The {@link #getFinalizerChecker()} method. This returns a {@link BiConsumer} that takes an
+ * object that owns resources and an expected number of unreleased resources. It will call the
+ * {@link Object#finalize()} method on the object using reflection and throw an
+ * {@link AssertionError} if the number of reported unreleased resources does not match the
+ * expected number.
+ * </li>
+ * </ul>
+ */
+public class CloseGuardSupport {
+
+ private static final TestRule CLOSE_GUARD_RULE = new FailTestWhenResourcesNotClosedRule();
+
+ /**
+ * Get a {@link TestRule} that will detect when resources that use the {@link CloseGuard}
+ * mechanism are not cleaned up properly by a test.
+ *
+ * <p>If the {@link CloseGuard} mechanism is not supported, e.g. on OpenJDK, then the returned
+ * rule does nothing.
+ */
+ public static TestRule getRule() {
+ return CLOSE_GUARD_RULE;
+ }
+
+ private CloseGuardSupport() {
+ }
+
+ /**
+ * Fails a test when resources are not cleaned up properly.
+ */
+ private static class FailTestWhenResourcesNotClosedRule implements TestRule {
+ /**
+ * Returns a {@link Statement} that will fail the test if it ends with unreleased resources.
+ * @param base the test to be run.
+ */
+ public Statement apply(Statement base, Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ // Get the previous tracker so that it can be restored afterwards.
+ CloseGuard.Tracker previousTracker = CloseGuard.getTracker();
+ // Get the previous enabled state so that it can be restored afterwards.
+ boolean previousEnabled = CloseGuard.isEnabled();
+ TestCloseGuardTracker tracker = new TestCloseGuardTracker();
+ Throwable thrown = null;
+ try {
+ // Set the test tracker and enable close guard detection.
+ CloseGuard.setTracker(tracker);
+ CloseGuard.setEnabled(true);
+ base.evaluate();
+ } catch (Throwable throwable) {
+ // Catch and remember the throwable so that it can be rethrown in the
+ // finally block.
+ thrown = throwable;
+ } finally {
+ // Restore the previous tracker and enabled state.
+ CloseGuard.setEnabled(previousEnabled);
+ CloseGuard.setTracker(previousTracker);
+
+ Collection<Throwable> allocationSites =
+ tracker.getAllocationSitesForUnreleasedResources();
+ if (!allocationSites.isEmpty()) {
+ if (thrown == null) {
+ thrown = new IllegalStateException(
+ "Unreleased resources found in test");
+ }
+ for (Throwable allocationSite : allocationSites) {
+ thrown.addSuppressed(allocationSite);
+ }
+ }
+ if (thrown != null) {
+ throw thrown;
+ }
+ }
+ }
+ };
+ }
+ }
+
+ /**
+ * A tracker that keeps a record of the allocation sites for all resources allocated but not
+ * yet released.
+ *
+ * <p>It only tracks resources allocated for the test thread.
+ */
+ private static class TestCloseGuardTracker implements CloseGuard.Tracker {
+
+ /**
+ * A set would be preferable but this is the closest that matches the concurrency
+ * requirements for the use case which prioritise speed of addition and removal over
+ * iteration and access.
+ */
+ private final Set<Throwable> allocationSites =
+ Collections.newSetFromMap(new ConcurrentHashMap<>());
+
+ private final Thread testThread = Thread.currentThread();
+
+ @Override
+ public void open(Throwable allocationSite) {
+ if (Thread.currentThread() == testThread) {
+ allocationSites.add(allocationSite);
+ }
+ }
+
+ @Override
+ public void close(Throwable allocationSite) {
+ // Closing the resource twice could pass null into here.
+ if (allocationSite != null) {
+ allocationSites.remove(allocationSite);
+ }
+ }
+
+ /**
+ * Get the collection of allocation sites for any unreleased resources.
+ */
+ Collection<Throwable> getAllocationSitesForUnreleasedResources() {
+ return new ArrayList<>(allocationSites);
+ }
+ }
+
+ private static final BiConsumer<Object, Integer> FINALIZER_CHECKER
+ = new BiConsumer<Object, Integer>() {
+ @Override
+ public void accept(Object resourceOwner, Integer expectedCount) {
+ finalizerChecker(resourceOwner, expectedCount);
+ }
+ };
+
+ /**
+ * Get access to a {@link BiConsumer} that will determine how many unreleased resources the
+ * first parameter owns and throw a {@link AssertionError} if that does not match the
+ * expected number of resources specified by the second parameter.
+ *
+ * <p>This uses a {@link BiConsumer} as it is a standard interface that is available in all
+ * environments. That helps avoid the caller from having compile time dependencies on this
+ * class which will not be available on OpenJDK.
+ */
+ public static BiConsumer<Object, Integer> getFinalizerChecker() {
+ return FINALIZER_CHECKER;
+ }
+
+ /**
+ * Checks that the supplied {@code resourceOwner} has overridden the {@link Object#finalize()}
+ * method and uses {@link CloseGuard#warnIfOpen()} correctly to detect when the resource is
+ * not released.
+ *
+ * @param resourceOwner the owner of the resource protected by {@link CloseGuard}.
+ * @param expectedCount the expected number of unreleased resources to be held by the owner.
+ *
+ */
+ private static void finalizerChecker(Object resourceOwner, int expectedCount) {
+ Class<?> clazz = resourceOwner.getClass();
+ Method finalizer = null;
+ while (clazz != null && clazz != Object.class) {
+ try {
+ finalizer = clazz.getDeclaredMethod("finalize");
+ break;
+ } catch (NoSuchMethodException e) {
+ // Carry on up the class hierarchy.
+ clazz = clazz.getSuperclass();
+ }
+ }
+
+ if (finalizer == null) {
+ // No finalizer method could be found.
+ throw new AssertionError("Class " + resourceOwner.getClass().getName()
+ + " does not have a finalize() method");
+ }
+
+ // Make the method accessible.
+ finalizer.setAccessible(true);
+
+ CloseGuard.Reporter oldReporter = CloseGuard.getReporter();
+ try {
+ CollectingReporter reporter = new CollectingReporter();
+ CloseGuard.setReporter(reporter);
+
+ // Invoke the finalizer to cause it to get CloseGuard to report a problem if it has
+ // not yet been closed.
+ try {
+ finalizer.invoke(resourceOwner);
+ } catch (ReflectiveOperationException e) {
+ throw new AssertionError(
+ "Could not invoke the finalizer() method on " + resourceOwner, e);
+ }
+
+ reporter.assertUnreleasedResources(expectedCount);
+ } finally {
+ CloseGuard.setReporter(oldReporter);
+ }
+ }
+
+ /**
+ * A {@link CloseGuard.Reporter} that collects any reports about unreleased resources.
+ */
+ private static class CollectingReporter implements CloseGuard.Reporter {
+
+ private final Thread callingThread = Thread.currentThread();
+
+ private final List<Throwable> unreleasedResourceAllocationSites = new ArrayList<>();
+
+ @Override
+ public void report(String message, Throwable allocationSite) {
+ // Only care about resources that are not reported on this thread.
+ if (callingThread == Thread.currentThread()) {
+ unreleasedResourceAllocationSites.add(allocationSite);
+ }
+ }
+
+ void assertUnreleasedResources(int expectedCount) {
+ int unreleasedResourceCount = unreleasedResourceAllocationSites.size();
+ if (unreleasedResourceCount == expectedCount) {
+ return;
+ }
+
+ AssertionError error = new AssertionError(
+ "Expected " + expectedCount + " unreleased resources, found "
+ + unreleasedResourceCount + "; see suppressed exceptions for details");
+ for (Throwable unreleasedResourceAllocationSite : unreleasedResourceAllocationSites) {
+ error.addSuppressed(unreleasedResourceAllocationSite);
+ }
+ throw error;
+ }
+ }
+}
diff --git a/dalvik/test-rules/src/test/java/dalvik/system/CloseGuardSupportTest.java b/dalvik/test-rules/src/test/java/dalvik/system/CloseGuardSupportTest.java
new file mode 100644
index 0000000..fe05710
--- /dev/null
+++ b/dalvik/test-rules/src/test/java/dalvik/system/CloseGuardSupportTest.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2016 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.Collections;
+import java.util.List;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.RunWith;
+import org.junit.runner.notification.Failure;
+import org.junit.runners.JUnit4;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+@RunWith(JUnit4.class)
+public class CloseGuardSupportTest {
+
+ @Test
+ public void testDoesReleaseResource() {
+ List<Failure> failures = JUnitCore.runClasses(DoesReleaseResource.class).getFailures();
+ assertEquals(Collections.emptyList(), failures);
+ }
+
+ public static class DoesReleaseResource {
+ @Rule public TestRule rule = CloseGuardSupport.getRule();
+ @Test public void test() {
+ CloseGuard closeGuard = CloseGuard.get();
+ closeGuard.open("test resource");
+ closeGuard.close();
+ }
+ }
+
+ @Test
+ public void testDoesReleaseResourceTwice() {
+ List<Failure> failures = JUnitCore.runClasses(DoesReleaseResourceTwice.class).getFailures();
+ assertEquals(Collections.emptyList(), failures);
+ }
+
+ public static class DoesReleaseResourceTwice {
+ @Rule public TestRule rule = CloseGuardSupport.getRule();
+ @Test public void test() {
+ CloseGuard closeGuard = CloseGuard.get();
+ closeGuard.open("test resource");
+ closeGuard.close();
+ closeGuard.close();
+ }
+ }
+
+ @Test
+ public void testDoesNotReleaseResource() {
+ List<Failure> failures = JUnitCore.runClasses(DoesNotReleaseResource.class).getFailures();
+ assertEquals("Failure count", 1, failures.size());
+ Failure failure = failures.get(0);
+ checkResourceNotReleased(failure, "Unreleased resources found in test");
+ }
+
+ public static class DoesNotReleaseResource {
+ @Rule public TestRule rule = CloseGuardSupport.getRule();
+ @Test public void test() {
+ CloseGuard closeGuard = CloseGuard.get();
+ closeGuard.open("test resource");
+ }
+ }
+
+ @Test
+ public void testDoesNotReleaseResourceDueToFailure() {
+ List<Failure> failures = JUnitCore
+ .runClasses(DoesNotReleaseResourceDueToFailure.class)
+ .getFailures();
+ assertEquals("Failure count", 1, failures.size());
+ Failure failure = failures.get(0);
+ checkResourceNotReleased(failure, "failure");
+ }
+
+ public static class DoesNotReleaseResourceDueToFailure {
+ @Rule public TestRule rule = CloseGuardSupport.getRule();
+ @Test public void test() {
+ CloseGuard closeGuard = CloseGuard.get();
+ closeGuard.open("test resource");
+ fail("failure");
+ }
+ }
+
+ @Test
+ public void testResourceOwnerDoesNotOverrideFinalize() {
+ List<Failure> failures = JUnitCore
+ .runClasses(ResourceOwnerDoesNotOverrideFinalize.class)
+ .getFailures();
+ assertEquals("Failure count", 1, failures.size());
+ Failure failure = failures.get(0);
+ assertEquals("Class java.lang.String does not have a finalize() method",
+ failure.getMessage());
+ }
+
+ public static class ResourceOwnerDoesNotOverrideFinalize {
+ @Rule public TestRule rule = CloseGuardSupport.getRule();
+ @Test
+ public void test() {
+ CloseGuardSupport.getFinalizerChecker().accept("not resource owner", 0);
+ }
+ }
+
+ @Test
+ public void testResourceOwnerOverridesFinalizeButDoesNotReportLeak() {
+ List<Failure> failures = JUnitCore
+ .runClasses(ResourceOwnerOverridesFinalizeButDoesNotReportLeak.class)
+ .getFailures();
+ assertEquals("Failure count", 1, failures.size());
+ Failure failure = failures.get(0);
+ assertEquals("Expected 1 unreleased resources, found 0;"
+ + " see suppressed exceptions for details",
+ failure.getMessage());
+ }
+
+ public static class ResourceOwnerOverridesFinalizeButDoesNotReportLeak {
+ @Rule public TestRule rule = CloseGuardSupport.getRule();
+ @Test
+ public void test() {
+ CloseGuardSupport.getFinalizerChecker().accept(new Object() {
+ @Override
+ protected void finalize() throws Throwable {
+ super.finalize();
+ }
+ }, 1);
+ }
+ }
+
+ @Test
+ public void testResourceOwnerOverridesFinalizeAndReportsLeak() {
+ List<Failure> failures = JUnitCore
+ .runClasses(ResourceOwnerOverridesFinalizeAndReportsLeak.class)
+ .getFailures();
+ assertEquals("Failure count", 1, failures.size());
+ Failure failure = failures.get(0);
+ checkResourceNotReleased(failure, "Unreleased resources found in test");
+ }
+
+ public static class ResourceOwnerOverridesFinalizeAndReportsLeak {
+ @Rule public TestRule rule = CloseGuardSupport.getRule();
+ @Test
+ public void test() {
+ CloseGuardSupport.getFinalizerChecker().accept(new Object() {
+ private CloseGuard guard = CloseGuard.get();
+ {
+ guard.open("test resource");
+ }
+ @Override
+ protected void finalize() throws Throwable {
+ guard.warnIfOpen();
+ super.finalize();
+ }
+ }, 1);
+ }
+ }
+
+ private void checkResourceNotReleased(Failure failure, String expectedMessage) {
+ @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+ Throwable exception = failure.getException();
+ assertEquals(expectedMessage, exception.getMessage());
+ Throwable[] suppressed = exception.getSuppressed();
+ assertEquals("Suppressed count", 1, suppressed.length);
+ exception = suppressed[0];
+ assertEquals("Explicit termination method 'test resource' not called",
+ exception.getMessage());
+ }
+}
diff --git a/luni/src/main/native/ExecStrings.cpp b/luni/src/main/native/ExecStrings.cpp
index a6a62e2..4f90431 100644
--- a/luni/src/main/native/ExecStrings.cpp
+++ b/luni/src/main/native/ExecStrings.cpp
@@ -20,7 +20,8 @@
#include <stdlib.h>
-#include "cutils/log.h"
+#include <android/log.h>
+
#include "ScopedLocalRef.h"
ExecStrings::ExecStrings(JNIEnv* env, jobjectArray java_string_array)
diff --git a/luni/src/main/native/IcuUtilities.cpp b/luni/src/main/native/IcuUtilities.cpp
index 98648a5..6b29e67 100644
--- a/luni/src/main/native/IcuUtilities.cpp
+++ b/luni/src/main/native/IcuUtilities.cpp
@@ -16,16 +16,17 @@
#define LOG_TAG "IcuUtilities"
+#include <android/log.h>
+
#include "IcuUtilities.h"
#include "JniConstants.h"
#include "JniException.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
-#include "cutils/log.h"
#include "unicode/strenum.h"
-#include "unicode/uloc.h"
#include "unicode/ustring.h"
+#include "unicode/uloc.h"
jobjectArray fromStringEnumeration(JNIEnv* env, UErrorCode& status, const char* provider, icu::StringEnumeration* se) {
if (maybeThrowIcuException(env, provider, status)) {
diff --git a/luni/src/main/native/Register.cpp b/luni/src/main/native/Register.cpp
index 52df40e..ec9d878 100644
--- a/luni/src/main/native/Register.cpp
+++ b/luni/src/main/native/Register.cpp
@@ -16,12 +16,13 @@
#define LOG_TAG "libcore" // We'll be next to "dalvikvm" in the log; make the distinction clear.
-#include "cutils/log.h"
+#include <stdlib.h>
+
+#include "android/log.h"
+
#include "JniConstants.h"
#include "ScopedLocalFrame.h"
-#include <stdlib.h>
-
// DalvikVM calls this on startup, so we can statically register all our native methods.
jint JNI_OnLoad(JavaVM* vm, void*) {
JNIEnv* env;
diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp
index e6f378e..7456028 100644
--- a/luni/src/main/native/libcore_icu_ICU.cpp
+++ b/luni/src/main/native/libcore_icu_ICU.cpp
@@ -16,6 +16,24 @@
#define LOG_TAG "ICU"
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <memory>
+#include <vector>
+
+#include <android/log.h>
+#include <android-base/unique_fd.h>
+
#include "IcuUtilities.h"
#include "JNIHelp.h"
#include "JniConstants.h"
@@ -24,7 +42,6 @@
#include "ScopedJavaUnicodeString.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
-#include "cutils/log.h"
#include "toStringArray.h"
#include "unicode/brkiter.h"
#include "unicode/calendar.h"
@@ -51,22 +68,6 @@
#include "ureslocs.h"
#include "valueOf.h"
-#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <string>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-#include <memory>
-#include <vector>
-
-#include <android-base/unique_fd.h>
-
class ScopedResourceBundle {
public:
explicit ScopedResourceBundle(UResourceBundle* bundle) : bundle_(bundle) {
diff --git a/luni/src/main/native/libcore_icu_NativeConverter.cpp b/luni/src/main/native/libcore_icu_NativeConverter.cpp
index bf938d1..f78ca19 100644
--- a/luni/src/main/native/libcore_icu_NativeConverter.cpp
+++ b/luni/src/main/native/libcore_icu_NativeConverter.cpp
@@ -15,6 +15,14 @@
#define LOG_TAG "NativeConverter"
+#include <stdlib.h>
+#include <string.h>
+
+#include <memory>
+#include <vector>
+
+#include <android/log.h>
+
#include "IcuUtilities.h"
#include "JNIHelp.h"
#include "JniConstants.h"
@@ -23,7 +31,6 @@
#include "ScopedPrimitiveArray.h"
#include "ScopedStringChars.h"
#include "ScopedUtfChars.h"
-#include "cutils/log.h"
#include "toStringArray.h"
#include "unicode/ucnv.h"
#include "unicode/ucnv_cb.h"
@@ -31,12 +38,6 @@
#include "unicode/ustring.h"
#include "unicode/utypes.h"
-#include <memory>
-#include <vector>
-
-#include <stdlib.h>
-#include <string.h>
-
#define NativeConverter_REPORT 0
#define NativeConverter_IGNORE 1
#define NativeConverter_REPLACE 2
diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp
index d0b3924..f8fd199 100644
--- a/luni/src/main/native/libcore_io_Posix.cpp
+++ b/luni/src/main/native/libcore_io_Posix.cpp
@@ -16,20 +16,6 @@
#define LOG_TAG "Posix"
-#include "AsynchronousCloseMonitor.h"
-#include "cutils/log.h"
-#include "ExecStrings.h"
-#include "JNIHelp.h"
-#include "JniConstants.h"
-#include "JniException.h"
-#include "NetworkUtilities.h"
-#include "Portability.h"
-#include "ScopedBytes.h"
-#include "ScopedLocalRef.h"
-#include "ScopedPrimitiveArray.h"
-#include "ScopedUtfChars.h"
-#include "toStringArray.h"
-
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
@@ -58,11 +44,26 @@
#include <sys/xattr.h>
#include <termios.h>
#include <unistd.h>
+
#include <memory>
+#include <android/log.h>
#include <android-base/file.h>
#include <android-base/strings.h>
+#include "AsynchronousCloseMonitor.h"
+#include "ExecStrings.h"
+#include "JNIHelp.h"
+#include "JniConstants.h"
+#include "JniException.h"
+#include "NetworkUtilities.h"
+#include "Portability.h"
+#include "ScopedBytes.h"
+#include "ScopedLocalRef.h"
+#include "ScopedPrimitiveArray.h"
+#include "ScopedUtfChars.h"
+#include "toStringArray.h"
+
#ifndef __unused
#define __unused __attribute__((__unused__))
#endif
diff --git a/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp b/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
index e27af69..aaf3ca1 100644
--- a/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
+++ b/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
@@ -16,6 +16,14 @@
#define LOG_TAG "ExpatParser"
+#include <expat.h>
+#include <string.h>
+
+#include <memory>
+
+#include <android/log.h>
+#include <android-base/stringprintf.h>
+
#include "JNIHelp.h"
#include "JniConstants.h"
#include "JniException.h"
@@ -24,15 +32,8 @@
#include "ScopedStringChars.h"
#include "ScopedUtfChars.h"
#include "jni.h"
-#include "cutils/log.h"
#include "unicode/unistr.h"
-#include <memory>
-
-#include <string.h>
-#include <expat.h>
-
-#include <android-base/stringprintf.h>
#define BUCKET_COUNT 128
diff --git a/luni/src/test/java/libcore/java/lang/ProcessBuilderTest.java b/luni/src/test/java/libcore/java/lang/ProcessBuilderTest.java
index bc4fe80..9254b8d 100644
--- a/luni/src/test/java/libcore/java/lang/ProcessBuilderTest.java
+++ b/luni/src/test/java/libcore/java/lang/ProcessBuilderTest.java
@@ -17,7 +17,6 @@
package libcore.java.lang;
import android.system.Os;
-
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
@@ -38,13 +37,13 @@
import java.util.concurrent.FutureTask;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import junit.framework.TestCase;
import libcore.io.IoUtils;
-import libcore.java.util.AbstractResourceLeakageDetectorTestCase;
import static java.lang.ProcessBuilder.Redirect.INHERIT;
import static java.lang.ProcessBuilder.Redirect.PIPE;
-public class ProcessBuilderTest extends AbstractResourceLeakageDetectorTestCase {
+public class ProcessBuilderTest extends TestCase {
private static final String TAG = ProcessBuilderTest.class.getSimpleName();
private static String shell() {
diff --git a/luni/src/test/java/libcore/java/text/DateFormatTest.java b/luni/src/test/java/libcore/java/text/DateFormatTest.java
new file mode 100644
index 0000000..8e215ab
--- /dev/null
+++ b/luni/src/test/java/libcore/java/text/DateFormatTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 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 libcore.java.text;
+
+import junit.framework.TestCase;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+public class DateFormatTest extends TestCase {
+
+ // Regression test for http://b/31762542. If this test fails it implies that changes to
+ // DateFormat.is24Hour will not be effective.
+ public void testIs24Hour_notCached() throws Exception {
+ Boolean originalIs24Hour = DateFormat.is24Hour;
+ try {
+ // These tests hardcode expectations for Locale.US.
+ DateFormat.is24Hour = null; // null == locale default (12 hour for US)
+ checkTimePattern(DateFormat.SHORT, "h:mm a");
+ checkTimePattern(DateFormat.MEDIUM, "h:mm:ss a");
+
+ DateFormat.is24Hour = true; // Explicit 24 hour.
+ checkTimePattern(DateFormat.SHORT, "HH:mm");
+ checkTimePattern(DateFormat.MEDIUM, "HH:mm:ss");
+
+ DateFormat.is24Hour = false; // Explicit 12 hour.
+ checkTimePattern(DateFormat.SHORT, "h:mm a");
+ checkTimePattern(DateFormat.MEDIUM, "h:mm:ss a");
+ } finally {
+ DateFormat.is24Hour = originalIs24Hour;
+ }
+ }
+
+ private static void checkTimePattern(int style, String expectedPattern) {
+ final Locale locale = Locale.US;
+ final Date current = new Date(1468250177000L); // 20160711 15:16:17 GMT
+ DateFormat format = DateFormat.getTimeInstance(style, locale);
+ String actualDateString = format.format(current);
+ SimpleDateFormat sdf = new SimpleDateFormat(expectedPattern, locale);
+ String expectedDateString = sdf.format(current);
+ assertEquals(expectedDateString, actualDateString);
+ }
+}
diff --git a/luni/src/test/java/libcore/java/util/AbstractResourceLeakageDetectorTestCase.java b/luni/src/test/java/libcore/java/util/AbstractResourceLeakageDetectorTestCase.java
deleted file mode 100644
index 5ea67d3..0000000
--- a/luni/src/test/java/libcore/java/util/AbstractResourceLeakageDetectorTestCase.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2014 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 libcore.java.util;
-
-import junit.framework.TestCase;
-
-/**
- * Ensures that resources used within a test are cleaned up; will detect problems with tests and
- * also with runtime.
- */
-public abstract class AbstractResourceLeakageDetectorTestCase extends TestCase {
- /**
- * The leakage detector.
- */
- private ResourceLeakageDetector detector;
-
- @Override
- protected void setUp() throws Exception {
- detector = ResourceLeakageDetector.newDetector();
- }
-
- @Override
- protected void tearDown() throws Exception {
- // If available check for resource leakage. At this point it is impossible to determine
- // whether the test has thrown an exception. If it has then the exception thrown by this
- // could hide that test failure; it largely depends on the test runner.
- if (detector != null) {
- detector.checkForLeaks();
- }
- }
-}
diff --git a/luni/src/test/java/libcore/java/util/ResourceLeakageDetector.java b/luni/src/test/java/libcore/java/util/ResourceLeakageDetector.java
deleted file mode 100644
index 954665a..0000000
--- a/luni/src/test/java/libcore/java/util/ResourceLeakageDetector.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2014 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 libcore.java.util;
-
-/**
- * Detects resource leakages for resources that are protected by <code>CloseGuard</code> mechanism.
- *
- * <p>If multiple instances of this are active at the same time, i.e. have been created but not yet
- * had their {@link #checkForLeaks()} method called then while they will report all the leakages
- * detected they may report the leakages caused by the code being tested by another detector.
- *
- * <p>The underlying CloseGuardMonitor is loaded using reflection to ensure that this will run,
- * albeit doing nothing, on the reference implementation.
- */
-public class ResourceLeakageDetector {
- /** The class for the CloseGuardMonitor, null if not supported. */
- private static final Class<?> CLOSE_GUARD_MONITOR_CLASS;
-
- static {
- ClassLoader classLoader = ResourceLeakageDetector.class.getClassLoader();
- Class<?> clazz;
- try {
- // Make sure that the CloseGuard class exists; this ensures that this is not running
- // on a RI JVM.
- classLoader.loadClass("dalvik.system.CloseGuard");
-
- // Load the monitor class for later instantiation.
- clazz = classLoader.loadClass("dalvik.system.CloseGuardMonitor");
-
- } catch (ClassNotFoundException e) {
- System.err.println("Resource leakage will not be detected; "
- + "this is expected in the reference implementation");
- e.printStackTrace(System.err);
-
- // Ignore, probably running in reference implementation.
- clazz = null;
- }
-
- CLOSE_GUARD_MONITOR_CLASS = clazz;
- }
-
- /**
- * The underlying CloseGuardMonitor that will perform the post test checks for resource
- * leakage.
- */
- private Runnable postTestChecker;
-
- /**
- * Create a new detector.
- *
- * @return The new {@link ResourceLeakageDetector}, its {@link #checkForLeaks()} method must be
- * called otherwise it will not clean up properly after itself.
- */
- public static ResourceLeakageDetector newDetector()
- throws Exception {
- return new ResourceLeakageDetector();
- }
-
- private ResourceLeakageDetector()
- throws Exception {
- if (CLOSE_GUARD_MONITOR_CLASS != null) {
- postTestChecker = (Runnable) CLOSE_GUARD_MONITOR_CLASS.newInstance();
- }
- }
-
- /**
- * Detect any leaks that have arisen since this was created.
- *
- * @throws Exception If any leaks were detected.
- */
- public void checkForLeaks() throws Exception {
- // If available check for resource leakage.
- if (postTestChecker != null) {
- postTestChecker.run();
- }
- }
-}
diff --git a/luni/src/test/java/libcore/java/util/ResourceLeakageDetectorTest.java b/luni/src/test/java/libcore/java/util/ResourceLeakageDetectorTest.java
deleted file mode 100644
index 5509f73..0000000
--- a/luni/src/test/java/libcore/java/util/ResourceLeakageDetectorTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2014 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 libcore.java.util;
-
-import dalvik.system.CloseGuard;
-import junit.framework.TestCase;
-
-/**
- * Test for {@link ResourceLeakageDetector}
- */
-public class ResourceLeakageDetectorTest extends TestCase {
- /**
- * This test will not work on RI as it does not support the <code>CloseGuard</code> or similar
- * mechanism.
- */
- // TODO(paulduffin): b/31542223 - Work out why this is failing in CTS, fix and reenable.
- public void notestDetectsUnclosedCloseGuard() throws Exception {
- ResourceLeakageDetector detector = ResourceLeakageDetector.newDetector();
- try {
- CloseGuard closeGuard = createCloseGuard();
- closeGuard.open("open");
- } finally {
- boolean leaksDetected = true;
- try {
- System.logI("Checking for leaks");
- detector.checkForLeaks();
- leaksDetected = false;
- } catch (AssertionError expected) {
- // The leak detector should throw this error.
- }
-
- if (!leaksDetected) {
- fail("Did not detect any leaks");
- }
- }
- }
-
- public void testIgnoresClosedCloseGuard() throws Exception {
- ResourceLeakageDetector detector = ResourceLeakageDetector.newDetector();
- try {
- CloseGuard closeGuard = createCloseGuard();
- closeGuard.open("open");
- closeGuard.close();
- } finally {
- detector.checkForLeaks();
- }
- }
-
- /**
- * Private method to ensure that the CloseGuard object is garbage collected.
- */
- private CloseGuard createCloseGuard() {
- final CloseGuard closeGuard = CloseGuard.get();
- new Object() {
- @Override
- protected void finalize() throws Throwable {
- try {
- closeGuard.warnIfOpen();
- } finally {
- super.finalize();
- }
- }
- };
-
- return closeGuard;
- }
-}
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java
index 61c6d03..9c562ee 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java
@@ -531,7 +531,7 @@
try {
uc2.getInputStream();
fail();
- } catch (Throwable expected) {
+ } catch (IOException expected) {
}
}
diff --git a/ojluni/src/main/java/java/io/ObjectInputStream.java b/ojluni/src/main/java/java/io/ObjectInputStream.java
index 0d66339..f562fe4 100644
--- a/ojluni/src/main/java/java/io/ObjectInputStream.java
+++ b/ojluni/src/main/java/java/io/ObjectInputStream.java
@@ -1832,6 +1832,8 @@
throws IOException
{
SerialCallbackContext oldContext = curContext;
+ if (oldContext != null)
+ oldContext.check();
curContext = null;
try {
boolean blocked = desc.hasBlockExternalData();
@@ -1856,6 +1858,8 @@
skipCustomData();
}
} finally {
+ if (oldContext != null)
+ oldContext.check();
curContext = oldContext;
}
/*
@@ -1884,13 +1888,14 @@
ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
for (int i = 0; i < slots.length; i++) {
ObjectStreamClass slotDesc = slots[i].desc;
- if (slots[i].hasData) {
- if (obj != null &&
- slotDesc.hasReadObjectMethod() &&
- handles.lookupException(passHandle) == null)
- {
- SerialCallbackContext oldContext = curContext;
+ if (slots[i].hasData) {
+ if (obj == null || handles.lookupException(passHandle) != null) {
+ defaultReadFields(null, slotDesc); // skip field values
+ } else if (slotDesc.hasReadObjectMethod()) {
+ SerialCallbackContext oldContext = curContext;
+ if (oldContext != null)
+ oldContext.check();
try {
curContext = new SerialCallbackContext(obj, slotDesc);
@@ -1907,6 +1912,8 @@
handles.markException(passHandle, ex);
} finally {
curContext.setUsed();
+ if (oldContext!= null)
+ oldContext.check();
curContext = oldContext;
}
@@ -1919,6 +1926,7 @@
} else {
defaultReadFields(obj, slotDesc);
}
+
if (slotDesc.hasWriteObjectData()) {
skipCustomData();
} else {
diff --git a/ojluni/src/main/java/java/io/ObjectOutputStream.java b/ojluni/src/main/java/java/io/ObjectOutputStream.java
index 5de2175..1503112 100644
--- a/ojluni/src/main/java/java/io/ObjectOutputStream.java
+++ b/ojluni/src/main/java/java/io/ObjectOutputStream.java
@@ -1298,7 +1298,7 @@
}
bout.setBlockDataMode(true);
- if (isCustomSubclass()) {
+ if (cl != null && isCustomSubclass()) {
ReflectUtil.checkPackageAccess(cl);
}
annotateProxyClass(cl);
@@ -1327,7 +1327,7 @@
Class<?> cl = desc.forClass();
bout.setBlockDataMode(true);
- if (isCustomSubclass()) {
+ if (cl != null && isCustomSubclass()) {
ReflectUtil.checkPackageAccess(cl);
}
annotateClass(cl);
@@ -1562,7 +1562,11 @@
private void defaultWriteFields(Object obj, ObjectStreamClass desc)
throws IOException
{
- // REMIND: perform conservative isInstance check here?
+ Class<?> cl = desc.forClass();
+ if (cl != null && obj != null && !cl.isInstance(obj)) {
+ throw new ClassCastException();
+ }
+
desc.checkDefaultSerialize();
int primDataSize = desc.getPrimDataSize();
diff --git a/ojluni/src/main/java/java/io/PipedInputStream.java b/ojluni/src/main/java/java/io/PipedInputStream.java
index 66cf19d..d7fb790 100644
--- a/ojluni/src/main/java/java/io/PipedInputStream.java
+++ b/ojluni/src/main/java/java/io/PipedInputStream.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -45,7 +45,7 @@
* The piped input stream contains a buffer,
* decoupling read operations from write operations,
* within limits.
- * A pipe is said to be <a name=BROKEN> <i>broken</i> </a> if a
+ * A pipe is said to be <a name="BROKEN"> <i>broken</i> </a> if a
* thread that was providing data bytes to the connected
* piped output stream is no longer alive.
*
@@ -123,7 +123,7 @@
* @param src the stream to connect to.
* @param pipeSize the size of the pipe's buffer.
* @exception IOException if an I/O error occurs.
- * @exception IllegalArgumentException if <code>pipeSize <= 0</code>.
+ * @exception IllegalArgumentException if {@code pipeSize <= 0}.
* @since 1.6
*/
public PipedInputStream(PipedOutputStream src, int pipeSize)
@@ -153,7 +153,7 @@
* connected} to a <code>PipedOutputStream</code> before being used.
*
* @param pipeSize the size of the pipe's buffer.
- * @exception IllegalArgumentException if <code>pipeSize <= 0</code>.
+ * @exception IllegalArgumentException if {@code pipeSize <= 0}.
* @since 1.6
*/
public PipedInputStream(int pipeSize) {
@@ -178,15 +178,14 @@
* unconnected piped output stream and <code>snk</code>
* is an unconnected piped input stream, they
* may be connected by either the call:
- * <p>
+ *
* <pre><code>snk.connect(src)</code> </pre>
* <p>
* or the call:
- * <p>
+ *
* <pre><code>src.connect(snk)</code> </pre>
* <p>
- * The two
- * calls have the same effect.
+ * The two calls have the same effect.
*
* @param src The piped output stream to connect to.
* @exception IOException if an I/O error occurs.
@@ -199,7 +198,7 @@
* Receives a byte of data. This method will block if no input is
* available.
* @param b the byte being received
- * @exception IOException If the pipe is <a href=#BROKEN> <code>broken</code></a>,
+ * @exception IOException If the pipe is <a href="#BROKEN"> <code>broken</code></a>,
* {@link #connect(java.io.PipedOutputStream) unconnected},
* closed, or if an I/O error occurs.
* @since JDK1.1
@@ -225,7 +224,7 @@
* @param b the buffer into which the data is received
* @param off the start offset of the data
* @param len the maximum number of bytes received
- * @exception IOException If the pipe is <a href=#BROKEN> broken</a>,
+ * @exception IOException If the pipe is <a href="#BROKEN"> broken</a>,
* {@link #connect(java.io.PipedOutputStream) unconnected},
* closed,or if an I/O error occurs.
*/
@@ -309,7 +308,7 @@
* stream is reached.
* @exception IOException if the pipe is
* {@link #connect(java.io.PipedOutputStream) unconnected},
- * <a href=#BROKEN> <code>broken</code></a>, closed,
+ * <a href="#BROKEN"> <code>broken</code></a>, closed,
* or if an I/O error occurs.
*/
public synchronized int read() throws IOException {
@@ -377,7 +376,7 @@
* @exception IndexOutOfBoundsException If <code>off</code> is negative,
* <code>len</code> is negative, or <code>len</code> is greater than
* <code>b.length - off</code>
- * @exception IOException if the pipe is <a href=#BROKEN> <code>broken</code></a>,
+ * @exception IOException if the pipe is <a href="#BROKEN"> <code>broken</code></a>,
* {@link #connect(java.io.PipedOutputStream) unconnected},
* closed, or if an I/O error occurs.
*/
@@ -435,7 +434,7 @@
* without blocking, or {@code 0} if this input stream has been
* closed by invoking its {@link #close()} method, or if the pipe
* is {@link #connect(java.io.PipedOutputStream) unconnected}, or
- * <a href=#BROKEN> <code>broken</code></a>.
+ * <a href="#BROKEN"> <code>broken</code></a>.
*
* @exception IOException if an I/O error occurs.
* @since JDK1.0.2
diff --git a/ojluni/src/main/java/java/io/PipedReader.java b/ojluni/src/main/java/java/io/PipedReader.java
index 93b7205..e4ec566 100644
--- a/ojluni/src/main/java/java/io/PipedReader.java
+++ b/ojluni/src/main/java/java/io/PipedReader.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -96,7 +96,7 @@
* @param src the stream to connect to.
* @param pipeSize the size of the pipe's buffer.
* @exception IOException if an I/O error occurs.
- * @exception IllegalArgumentException if <code>pipeSize <= 0</code>.
+ * @exception IllegalArgumentException if {@code pipeSize <= 0}.
* @since 1.6
*/
public PipedReader(PipedWriter src, int pipeSize) throws IOException {
@@ -125,7 +125,7 @@
* before being used.
*
* @param pipeSize the size of the pipe's buffer.
- * @exception IllegalArgumentException if <code>pipeSize <= 0</code>.
+ * @exception IllegalArgumentException if {@code pipeSize <= 0}.
* @since 1.6
*/
public PipedReader(int pipeSize) {
@@ -150,15 +150,14 @@
* unconnected piped writer and <code>snk</code>
* is an unconnected piped reader, they
* may be connected by either the call:
- * <p>
+ *
* <pre><code>snk.connect(src)</code> </pre>
* <p>
* or the call:
- * <p>
+ *
* <pre><code>src.connect(snk)</code> </pre>
* <p>
- * The two
- * calls have the same effect.
+ * The two calls have the same effect.
*
* @param src The piped writer to connect to.
* @exception IOException if an I/O error occurs.
diff --git a/ojluni/src/main/java/java/io/PrintStream.java b/ojluni/src/main/java/java/io/PrintStream.java
index 6968527..08bb3a3 100644
--- a/ojluni/src/main/java/java/io/PrintStream.java
+++ b/ojluni/src/main/java/java/io/PrintStream.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -302,7 +302,7 @@
* creating the file
*
* @throws SecurityException
- * If a security manager is presentand {@link
+ * If a security manager is present and {@link
* SecurityManager#checkWrite checkWrite(file.getPath())}
* denies write access to the file
*
@@ -869,7 +869,7 @@
* <tt>null</tt> argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
@@ -919,7 +919,7 @@
* <tt>null</tt> argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
@@ -962,7 +962,7 @@
* <tt>null</tt> argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
@@ -1019,7 +1019,7 @@
* <tt>null</tt> argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
diff --git a/ojluni/src/main/java/java/io/PrintWriter.java b/ojluni/src/main/java/java/io/PrintWriter.java
index 102c3a2..9287a19 100644
--- a/ojluni/src/main/java/java/io/PrintWriter.java
+++ b/ojluni/src/main/java/java/io/PrintWriter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -784,7 +784,7 @@
* <tt>null</tt> argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
@@ -835,7 +835,7 @@
* <tt>null</tt> argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
@@ -879,7 +879,7 @@
* <tt>null</tt> argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
@@ -939,7 +939,7 @@
* <tt>null</tt> argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
diff --git a/ojluni/src/main/java/java/io/PushbackInputStream.java b/ojluni/src/main/java/java/io/PushbackInputStream.java
index af0b525..b44848d 100644
--- a/ojluni/src/main/java/java/io/PushbackInputStream.java
+++ b/ojluni/src/main/java/java/io/PushbackInputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -85,7 +85,7 @@
*
* @param in the input stream from which bytes will be read.
* @param size the size of the pushback buffer.
- * @exception IllegalArgumentException if size is <= 0
+ * @exception IllegalArgumentException if {@code size <= 0}
* @since JDK1.1
*/
public PushbackInputStream(InputStream in, int size) {
diff --git a/ojluni/src/main/java/java/io/PushbackReader.java b/ojluni/src/main/java/java/io/PushbackReader.java
index 2f5b18c..f918621 100644
--- a/ojluni/src/main/java/java/io/PushbackReader.java
+++ b/ojluni/src/main/java/java/io/PushbackReader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -47,7 +47,7 @@
*
* @param in The reader from which characters will be read
* @param size The size of the pushback buffer
- * @exception IllegalArgumentException if size is <= 0
+ * @exception IllegalArgumentException if {@code size <= 0}
*/
public PushbackReader(Reader in, int size) {
super(in);
diff --git a/ojluni/src/main/java/java/io/Reader.java b/ojluni/src/main/java/java/io/Reader.java
index e2248c4..1c9cca6 100644
--- a/ojluni/src/main/java/java/io/Reader.java
+++ b/ojluni/src/main/java/java/io/Reader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -91,7 +91,7 @@
* -1 if this source of characters is at its end
* @throws IOException if an I/O error occurs
* @throws NullPointerException if target is null
- * @throws ReadOnlyBufferException if target is a read only buffer
+ * @throws java.nio.ReadOnlyBufferException if target is a read only buffer
* @since 1.5
*/
public int read(java.nio.CharBuffer target) throws IOException {
diff --git a/ojluni/src/main/java/java/io/SerialCallbackContext.java b/ojluni/src/main/java/java/io/SerialCallbackContext.java
index 748d38e..4009087 100644
--- a/ojluni/src/main/java/java/io/SerialCallbackContext.java
+++ b/ojluni/src/main/java/java/io/SerialCallbackContext.java
@@ -60,6 +60,13 @@
return desc;
}
+ public void check() throws NotActiveException {
+ if (thread != null && thread != Thread.currentThread()) {
+ throw new NotActiveException(
+ "expected thread: " + thread + ", but got: " + Thread.currentThread());
+ }
+ }
+
private void checkAndSetUsed() throws NotActiveException {
if (thread != Thread.currentThread()) {
throw new NotActiveException(
diff --git a/ojluni/src/main/java/java/io/Serializable.java b/ojluni/src/main/java/java/io/Serializable.java
index 83bfe03..96ea33c 100644
--- a/ojluni/src/main/java/java/io/Serializable.java
+++ b/ojluni/src/main/java/java/io/Serializable.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -55,7 +55,7 @@
*
* Classes that require special handling during the serialization and
* deserialization process must implement special methods with these exact
- * signatures: <p>
+ * signatures:
*
* <PRE>
* private void writeObject(java.io.ObjectOutputStream out)
@@ -101,7 +101,7 @@
*
* <p>Serializable classes that need to designate an alternative object to be
* used when writing an object to the stream should implement this
- * special method with the exact signature: <p>
+ * special method with the exact signature:
*
* <PRE>
* ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
@@ -115,7 +115,7 @@
*
* Classes that need to designate a replacement when an instance of it
* is read from the stream should implement this special method with the
- * exact signature.<p>
+ * exact signature.
*
* <PRE>
* ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
@@ -133,7 +133,7 @@
* deserialization will result in an {@link InvalidClassException}. A
* serializable class can declare its own serialVersionUID explicitly by
* declaring a field named <code>"serialVersionUID"</code> that must be static,
- * final, and of type <code>long</code>:<p>
+ * final, and of type <code>long</code>:
*
* <PRE>
* ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
diff --git a/ojluni/src/main/java/java/io/SerializablePermission.java b/ojluni/src/main/java/java/io/SerializablePermission.java
index ab1ccf4..e11f3ee 100644
--- a/ojluni/src/main/java/java/io/SerializablePermission.java
+++ b/ojluni/src/main/java/java/io/SerializablePermission.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/io/StreamTokenizer.java b/ojluni/src/main/java/java/io/StreamTokenizer.java
index 81ec5d5..3c7c7cc 100644
--- a/ojluni/src/main/java/java/io/StreamTokenizer.java
+++ b/ojluni/src/main/java/java/io/StreamTokenizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
import java.util.Arrays;
/**
- * The <code>StreamTokenizer</code> class takes an input stream and
+ * The {@code StreamTokenizer} class takes an input stream and
* parses it into "tokens", allowing the tokens to be
* read one at a time. The parsing process is controlled by a table
* and a number of flags that can be set to various states. The
@@ -36,7 +36,7 @@
* strings, and various comment styles.
* <p>
* Each byte read from the input stream is regarded as a character
- * in the range <code>'\u0000'</code> through <code>'\u00FF'</code>.
+ * in the range {@code '\u005Cu0000'} through {@code '\u005Cu00FF'}.
* The character value is used to look up five possible attributes of
* the character: <i>white space</i>, <i>alphabetic</i>,
* <i>numeric</i>, <i>string quote</i>, and <i>comment character</i>.
@@ -53,8 +53,8 @@
* <p>
* A typical application first constructs an instance of this class,
* sets up the syntax tables, and then repeatedly loops calling the
- * <code>nextToken</code> method in each iteration of the loop until
- * it returns the value <code>TT_EOF</code>.
+ * {@code nextToken} method in each iteration of the loop until
+ * it returns the value {@code TT_EOF}.
*
* @author James Gosling
* @see java.io.StreamTokenizer#nextToken()
@@ -99,19 +99,19 @@
private static final byte CT_COMMENT = 16;
/**
- * After a call to the <code>nextToken</code> method, this field
+ * After a call to the {@code nextToken} method, this field
* contains the type of the token just read. For a single character
* token, its value is the single character, converted to an integer.
* For a quoted string token, its value is the quote character.
* Otherwise, its value is one of the following:
* <ul>
- * <li><code>TT_WORD</code> indicates that the token is a word.
- * <li><code>TT_NUMBER</code> indicates that the token is a number.
- * <li><code>TT_EOL</code> indicates that the end of line has been read.
+ * <li>{@code TT_WORD} indicates that the token is a word.
+ * <li>{@code TT_NUMBER} indicates that the token is a number.
+ * <li>{@code TT_EOL} indicates that the end of line has been read.
* The field can only have this value if the
- * <code>eolIsSignificant</code> method has been called with the
- * argument <code>true</code>.
- * <li><code>TT_EOF</code> indicates that the end of the input stream
+ * {@code eolIsSignificant} method has been called with the
+ * argument {@code true}.
+ * <li>{@code TT_EOF} indicates that the end of the input stream
* has been reached.
* </ul>
* <p>
@@ -160,8 +160,8 @@
* the string.
* <p>
* The current token is a word when the value of the
- * <code>ttype</code> field is <code>TT_WORD</code>. The current token is
- * a quoted string token when the value of the <code>ttype</code> field is
+ * {@code ttype} field is {@code TT_WORD}. The current token is
+ * a quoted string token when the value of the {@code ttype} field is
* a quote character.
* <p>
* The initial value of this field is null.
@@ -175,7 +175,7 @@
/**
* If the current token is a number, this field contains the value
* of that number. The current token is a number when the value of
- * the <code>ttype</code> field is <code>TT_NUMBER</code>.
+ * the {@code ttype} field is {@code TT_NUMBER}.
* <p>
* The initial value of this field is 0.0.
*
@@ -201,14 +201,14 @@
* stream. The stream tokenizer is initialized to the following
* default state:
* <ul>
- * <li>All byte values <code>'A'</code> through <code>'Z'</code>,
- * <code>'a'</code> through <code>'z'</code>, and
- * <code>'\u00A0'</code> through <code>'\u00FF'</code> are
+ * <li>All byte values {@code 'A'} through {@code 'Z'},
+ * {@code 'a'} through {@code 'z'}, and
+ * {@code '\u005Cu00A0'} through {@code '\u005Cu00FF'} are
* considered to be alphabetic.
- * <li>All byte values <code>'\u0000'</code> through
- * <code>'\u0020'</code> are considered to be white space.
- * <li><code>'/'</code> is a comment character.
- * <li>Single quote <code>'\''</code> and double quote <code>'"'</code>
+ * <li>All byte values {@code '\u005Cu0000'} through
+ * {@code '\u005Cu0020'} are considered to be white space.
+ * <li>{@code '/'} is a comment character.
+ * <li>Single quote {@code '\u005C''} and double quote {@code '"'}
* are string quote characters.
* <li>Numbers are parsed.
* <li>Ends of lines are treated as white space, not as separate tokens.
@@ -252,7 +252,7 @@
/**
* Resets this tokenizer's syntax table so that all characters are
- * "ordinary." See the <code>ordinaryChar</code> method
+ * "ordinary." See the {@code ordinaryChar} method
* for more information on a character being ordinary.
*
* @see java.io.StreamTokenizer#ordinaryChar(int)
@@ -305,7 +305,7 @@
* Specifies that all characters <i>c</i> in the range
* <code>low <= <i>c</i> <= high</code>
* are "ordinary" in this tokenizer. See the
- * <code>ordinaryChar</code> method for more information on a
+ * {@code ordinaryChar} method for more information on a
* character being ordinary.
*
* @param low the low end of the range.
@@ -327,12 +327,12 @@
* character has as a comment character, word component, string
* delimiter, white space, or number character. When such a character
* is encountered by the parser, the parser treats it as a
- * single-character token and sets <code>ttype</code> field to the
+ * single-character token and sets {@code ttype} field to the
* character value.
*
* <p>Making a line terminator character "ordinary" may interfere
- * with the ability of a <code>StreamTokenizer</code> to count
- * lines. The <code>lineno</code> method may no longer reflect
+ * with the ability of a {@code StreamTokenizer} to count
+ * lines. The {@code lineno} method may no longer reflect
* the presence of such terminator characters in its line count.
*
* @param ch the character.
@@ -361,9 +361,9 @@
* Specifies that matching pairs of this character delimit string
* constants in this tokenizer.
* <p>
- * When the <code>nextToken</code> method encounters a string
- * constant, the <code>ttype</code> field is set to the string
- * delimiter and the <code>sval</code> field is set to the body of
+ * When the {@code nextToken} method encounters a string
+ * constant, the {@code ttype} field is set to the string
+ * delimiter and the {@code sval} field is set to the body of
* the string.
* <p>
* If a string quote character is encountered, then a string is
@@ -371,7 +371,7 @@
* the string quote character, up to (but not including) the next
* occurrence of that same string quote character, or a line
* terminator, or end of file. The usual escape sequences such as
- * <code>"\n"</code> and <code>"\t"</code> are recognized and
+ * {@code "\u005Cn"} and {@code "\u005Ct"} are recognized and
* converted to single characters as the string is parsed.
*
* <p>Any other attribute settings for the specified character are cleared.
@@ -398,9 +398,9 @@
* <p>
* When the parser encounters a word token that has the format of a
* double precision floating-point number, it treats the token as a
- * number rather than a word, by setting the <code>ttype</code>
- * field to the value <code>TT_NUMBER</code> and putting the numeric
- * value of the token into the <code>nval</code> field.
+ * number rather than a word, by setting the {@code ttype}
+ * field to the value {@code TT_NUMBER} and putting the numeric
+ * value of the token into the {@code nval} field.
*
* @see java.io.StreamTokenizer#nval
* @see java.io.StreamTokenizer#TT_NUMBER
@@ -416,21 +416,21 @@
/**
* Determines whether or not ends of line are treated as tokens.
* If the flag argument is true, this tokenizer treats end of lines
- * as tokens; the <code>nextToken</code> method returns
- * <code>TT_EOL</code> and also sets the <code>ttype</code> field to
+ * as tokens; the {@code nextToken} method returns
+ * {@code TT_EOL} and also sets the {@code ttype} field to
* this value when an end of line is read.
* <p>
* A line is a sequence of characters ending with either a
- * carriage-return character (<code>'\r'</code>) or a newline
- * character (<code>'\n'</code>). In addition, a carriage-return
+ * carriage-return character ({@code '\u005Cr'}) or a newline
+ * character ({@code '\u005Cn'}). In addition, a carriage-return
* character followed immediately by a newline character is treated
* as a single end-of-line token.
* <p>
- * If the <code>flag</code> is false, end-of-line characters are
+ * If the {@code flag} is false, end-of-line characters are
* treated as white space and serve only to separate tokens.
*
- * @param flag <code>true</code> indicates that end-of-line characters
- * are separate tokens; <code>false</code> indicates that
+ * @param flag {@code true} indicates that end-of-line characters
+ * are separate tokens; {@code false} indicates that
* end-of-line characters are white space.
* @see java.io.StreamTokenizer#nextToken()
* @see java.io.StreamTokenizer#ttype
@@ -442,14 +442,14 @@
/**
* Determines whether or not the tokenizer recognizes C-style comments.
- * If the flag argument is <code>true</code>, this stream tokenizer
+ * If the flag argument is {@code true}, this stream tokenizer
* recognizes C-style comments. All text between successive
- * occurrences of <code>/*</code> and <code>*/</code> are discarded.
+ * occurrences of {@code /*} and <code>*/</code> are discarded.
* <p>
- * If the flag argument is <code>false</code>, then C-style comments
+ * If the flag argument is {@code false}, then C-style comments
* are not treated specially.
*
- * @param flag <code>true</code> indicates to recognize and ignore
+ * @param flag {@code true} indicates to recognize and ignore
* C-style comments.
*/
public void slashStarComments(boolean flag) {
@@ -458,15 +458,15 @@
/**
* Determines whether or not the tokenizer recognizes C++-style comments.
- * If the flag argument is <code>true</code>, this stream tokenizer
+ * If the flag argument is {@code true}, this stream tokenizer
* recognizes C++-style comments. Any occurrence of two consecutive
- * slash characters (<code>'/'</code>) is treated as the beginning of
+ * slash characters ({@code '/'}) is treated as the beginning of
* a comment that extends to the end of the line.
* <p>
- * If the flag argument is <code>false</code>, then C++-style
+ * If the flag argument is {@code false}, then C++-style
* comments are not treated specially.
*
- * @param flag <code>true</code> indicates to recognize and ignore
+ * @param flag {@code true} indicates to recognize and ignore
* C++-style comments.
*/
public void slashSlashComments(boolean flag) {
@@ -475,16 +475,16 @@
/**
* Determines whether or not word token are automatically lowercased.
- * If the flag argument is <code>true</code>, then the value in the
- * <code>sval</code> field is lowercased whenever a word token is
- * returned (the <code>ttype</code> field has the
- * value <code>TT_WORD</code> by the <code>nextToken</code> method
+ * If the flag argument is {@code true}, then the value in the
+ * {@code sval} field is lowercased whenever a word token is
+ * returned (the {@code ttype} field has the
+ * value {@code TT_WORD} by the {@code nextToken} method
* of this tokenizer.
* <p>
- * If the flag argument is <code>false</code>, then the
- * <code>sval</code> field is not modified.
+ * If the flag argument is {@code false}, then the
+ * {@code sval} field is not modified.
*
- * @param fl <code>true</code> indicates that all word tokens should
+ * @param fl {@code true} indicates that all word tokens should
* be lowercased.
* @see java.io.StreamTokenizer#nextToken()
* @see java.io.StreamTokenizer#ttype
@@ -506,9 +506,9 @@
/**
* Parses the next token from the input stream of this tokenizer.
- * The type of the next token is returned in the <code>ttype</code>
+ * The type of the next token is returned in the {@code ttype}
* field. Additional information about the token may be in the
- * <code>nval</code> field or the <code>sval</code> field of this
+ * {@code nval} field or the {@code sval} field of this
* tokenizer.
* <p>
* Typical clients of this
@@ -516,7 +516,7 @@
* calling nextToken to parse successive tokens until TT_EOF
* is returned.
*
- * @return the value of the <code>ttype</code> field.
+ * @return the value of the {@code ttype} field.
* @exception IOException if an I/O error occurs.
* @see java.io.StreamTokenizer#nval
* @see java.io.StreamTokenizer#sval
@@ -752,10 +752,10 @@
}
/**
- * Causes the next call to the <code>nextToken</code> method of this
- * tokenizer to return the current value in the <code>ttype</code>
- * field, and not to modify the value in the <code>nval</code> or
- * <code>sval</code> field.
+ * Causes the next call to the {@code nextToken} method of this
+ * tokenizer to return the current value in the {@code ttype}
+ * field, and not to modify the value in the {@code nval} or
+ * {@code sval} field.
*
* @see java.io.StreamTokenizer#nextToken()
* @see java.io.StreamTokenizer#nval
diff --git a/ojluni/src/main/java/java/io/StringReader.java b/ojluni/src/main/java/java/io/StringReader.java
index 3778408..ce9ff60 100644
--- a/ojluni/src/main/java/java/io/StringReader.java
+++ b/ojluni/src/main/java/java/io/StringReader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -163,7 +163,7 @@
* is no actual limit, so this argument must not
* be negative, but is otherwise ignored.
*
- * @exception IllegalArgumentException If readAheadLimit is < 0
+ * @exception IllegalArgumentException If {@code readAheadLimit < 0}
* @exception IOException If an I/O error occurs
*/
public void mark(int readAheadLimit) throws IOException {
diff --git a/ojluni/src/main/java/java/io/UnixFileSystem.java b/ojluni/src/main/java/java/io/UnixFileSystem.java
index 6ce3f6f..1659b17 100644
--- a/ojluni/src/main/java/java/io/UnixFileSystem.java
+++ b/ojluni/src/main/java/java/io/UnixFileSystem.java
@@ -236,6 +236,7 @@
private native int getBooleanAttributes0(String abspath);
+ // Android-changed: Added thread policy check
public int getBooleanAttributes(File f) {
BlockGuard.getThreadPolicy().onReadFromDisk();
@@ -245,43 +246,43 @@
return rv | (hidden ? BA_HIDDEN : 0);
}
+ // Android-changed: Added thread policy check
public boolean checkAccess(File f, int access) {
BlockGuard.getThreadPolicy().onReadFromDisk();
return checkAccess0(f, access);
}
-
private native boolean checkAccess0(File f, int access);
+ // Android-changed: Added thread policy check
public long getLastModifiedTime(File f) {
BlockGuard.getThreadPolicy().onReadFromDisk();
return getLastModifiedTime0(f);
}
-
private native long getLastModifiedTime0(File f);
+ // Android-changed: Added thread policy check
public long getLength(File f) {
BlockGuard.getThreadPolicy().onReadFromDisk();
return getLength0(f);
}
-
private native long getLength0(File f);
+ // Android-changed: Added thread policy check
public boolean setPermission(File f, int access, boolean enable, boolean owneronly) {
BlockGuard.getThreadPolicy().onWriteToDisk();
return setPermission0(f, access, enable, owneronly);
}
-
private native boolean setPermission0(File f, int access, boolean enable, boolean owneronly);
/* -- File operations -- */
-
+ // Android-changed: Added thread policy check
public boolean createFileExclusively(String path) throws IOException {
BlockGuard.getThreadPolicy().onWriteToDisk();
return createFileExclusively0(path);
}
-
private native boolean createFileExclusively0(String path) throws IOException;
+ // Android-changed: Added thread policy check
public boolean delete(File f) {
// Keep canonicalization caches in sync after file deletion
// and renaming operations. Could be more clever than this
@@ -296,20 +297,21 @@
private native boolean delete0(File f);
+ // Android-changed: Added thread policy check
public String[] list(File f) {
BlockGuard.getThreadPolicy().onReadFromDisk();
return list0(f);
}
-
private native String[] list0(File f);
+ // Android-changed: Added thread policy check
public boolean createDirectory(File f) {
BlockGuard.getThreadPolicy().onWriteToDisk();
return createDirectory0(f);
}
-
private native boolean createDirectory0(File f);
+ // Android-changed: Added thread policy check
public boolean rename(File f1, File f2) {
// Keep canonicalization caches in sync after file deletion
// and renaming operations. Could be more clever than this
@@ -324,18 +326,18 @@
private native boolean rename0(File f1, File f2);
+ // Android-changed: Added thread policy check
public boolean setLastModifiedTime(File f, long time) {
BlockGuard.getThreadPolicy().onWriteToDisk();
return setLastModifiedTime0(f, time);
}
-
private native boolean setLastModifiedTime0(File f, long time);
+ // Android-changed: Added thread policy check
public boolean setReadOnly(File f) {
BlockGuard.getThreadPolicy().onWriteToDisk();
return setReadOnly0(f);
}
-
private native boolean setReadOnly0(File f);
@@ -354,12 +356,12 @@
}
/* -- Disk usage -- */
+ // Android-changed: Added thread policy check
public long getSpace(File f, int t) {
BlockGuard.getThreadPolicy().onReadFromDisk();
return getSpace0(f, t);
}
-
private native long getSpace0(File f, int t);
/* -- Basic infrastructure -- */
diff --git a/ojluni/src/main/java/java/io/Writer.java b/ojluni/src/main/java/java/io/Writer.java
index f0c6db4..8747a13 100644
--- a/ojluni/src/main/java/java/io/Writer.java
+++ b/ojluni/src/main/java/java/io/Writer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -57,7 +57,7 @@
/**
* Size of writeBuffer, must be >= 1
*/
- private final int writeBufferSize = 1024;
+ private static final int WRITE_BUFFER_SIZE = 1024;
/**
* The object used to synchronize operations on this stream. For
@@ -107,7 +107,7 @@
public void write(int c) throws IOException {
synchronized (lock) {
if (writeBuffer == null){
- writeBuffer = new char[writeBufferSize];
+ writeBuffer = new char[WRITE_BUFFER_SIZE];
}
writeBuffer[0] = (char) c;
write(writeBuffer, 0, 1);
@@ -180,9 +180,9 @@
public void write(String str, int off, int len) throws IOException {
synchronized (lock) {
char cbuf[];
- if (len <= writeBufferSize) {
+ if (len <= WRITE_BUFFER_SIZE) {
if (writeBuffer == null) {
- writeBuffer = new char[writeBufferSize];
+ writeBuffer = new char[WRITE_BUFFER_SIZE];
}
cbuf = writeBuffer;
} else { // Don't permanently allocate very large buffers.
diff --git a/ojluni/src/main/java/java/lang/invoke/MethodHandle.java b/ojluni/src/main/java/java/lang/invoke/MethodHandle.java
index ef4f7fe..0c27b99 100644
--- a/ojluni/src/main/java/java/lang/invoke/MethodHandle.java
+++ b/ojluni/src/main/java/java/lang/invoke/MethodHandle.java
@@ -455,16 +455,16 @@
* field_id in the equivalent instruction.
*/
- /** @hide */ public static final int INVOKE_VIRTUAL = 0x6e;
- /** @hide */ public static final int INVOKE_SUPER = 0x6f;
- /** @hide */ public static final int INVOKE_DIRECT = 0x70;
- /** @hide */ public static final int INVOKE_STATIC = 0x71;
- /** @hide */ public static final int INVOKE_INTERFACE = 0x72;
+ /** @hide */ public static final int INVOKE_VIRTUAL = 0;
+ /** @hide */ public static final int INVOKE_SUPER = 1;
+ /** @hide */ public static final int INVOKE_DIRECT = 2;
+ /** @hide */ public static final int INVOKE_STATIC = 3;
+ /** @hide */ public static final int INVOKE_INTERFACE = 4;
- /** @hide */ public static final int SGET = 0x60;
- /** @hide */ public static final int SPUT = 0x67;
- /** @hide */ public static final int IGET = 0x52;
- /** @hide */ public static final int IPUT = 0x59;
+ /** @hide */ public static final int SGET = 5;
+ /** @hide */ public static final int SPUT = 6;
+ /** @hide */ public static final int IGET = 7;
+ /** @hide */ public static final int IPUT = 8;
// The kind of this method handle (used by the runtime). This is one of the INVOKE_*
// constants or SGET/SPUT, IGET/IPUT.
diff --git a/ojluni/src/main/java/java/net/Inet6AddressImpl.java b/ojluni/src/main/java/java/net/Inet6AddressImpl.java
index 203ccb8..3029acc 100644
--- a/ojluni/src/main/java/java/net/Inet6AddressImpl.java
+++ b/ojluni/src/main/java/java/net/Inet6AddressImpl.java
@@ -28,13 +28,17 @@
import android.system.GaiException;
import android.system.StructAddrinfo;
import dalvik.system.BlockGuard;
+
+import libcore.io.IoBridge;
import libcore.io.Libcore;
+import java.io.FileDescriptor;
import java.io.IOException;
import static android.system.OsConstants.AF_UNSPEC;
import static android.system.OsConstants.AI_ADDRCONFIG;
import static android.system.OsConstants.EACCES;
+import static android.system.OsConstants.ECONNREFUSED;
import static android.system.OsConstants.SOCK_STREAM;
/*
@@ -140,9 +144,12 @@
@Override
public boolean isReachable(InetAddress addr, int timeout, NetworkInterface netif, int ttl) throws IOException {
- byte[] ifaddr = null;
- int scope = -1;
- int netif_scope = -1;
+ // Android-changed: rewritten on the top of IoBridge and Libcore.os
+ // TODO (b/31926888): try ICMP first (http://code.google.com/p/android/issues/detail?id=20106)
+
+ // No good, let's fall back to TCP
+ FileDescriptor fd = IoBridge.socket(true);
+ InetAddress sourceAddr = null;
if (netif != null) {
/*
* Let's make sure we bind to an address of the proper family.
@@ -155,31 +162,32 @@
while (it.hasMoreElements()) {
inetaddr = it.nextElement();
if (inetaddr.getClass().isInstance(addr)) {
- ifaddr = inetaddr.getAddress();
- if (inetaddr instanceof Inet6Address) {
- netif_scope = ((Inet6Address) inetaddr).getScopeId();
- }
+ sourceAddr = inetaddr;
break;
}
}
- if (ifaddr == null) {
+
+ if (sourceAddr == null) {
// Interface doesn't support the address family of
// the destination
return false;
}
}
- if (addr instanceof Inet6Address)
- scope = ((Inet6Address) addr).getScopeId();
- BlockGuard.getThreadPolicy().onNetwork();
-
- // Never throw an IOException from isReachable. If something terrible happens either
- // with the network interface in question (or with the destination), then just return
- // false (i.e, state that the address is unreachable.
try {
- return isReachable0(addr.getAddress(), scope, timeout, ifaddr, ttl, netif_scope);
- } catch (IOException ioe) {
- return false;
+ if (sourceAddr != null) {
+ IoBridge.bind(fd, sourceAddr, 0);
+ }
+ IoBridge.connect(fd, addr, 7 /* Echo-protocol port */, timeout);
+ return true;
+ } catch (IOException e) {
+ // Connection refused by remote (ECONNREFUSED) implies reachable. Otherwise silently
+ // ignore the exception and return false.
+ Throwable cause = e.getCause();
+ return cause instanceof ErrnoException
+ && ((ErrnoException) cause).errno == ECONNREFUSED;
+ } finally {
+ IoBridge.closeAndSignalBlockedThreads(fd);
}
}
@@ -216,5 +224,4 @@
}
private native String getHostByAddr0(byte[] addr) throws UnknownHostException;
- private native boolean isReachable0(byte[] addr, int scope, int timeout, byte[] inf, int ttl, int if_scope) throws IOException;
}
diff --git a/ojluni/src/main/java/java/text/SimpleDateFormat.java b/ojluni/src/main/java/java/text/SimpleDateFormat.java
index b17245f..de2a93e 100644
--- a/ojluni/src/main/java/java/text/SimpleDateFormat.java
+++ b/ojluni/src/main/java/java/text/SimpleDateFormat.java
@@ -534,12 +534,6 @@
private static final String GMT = "GMT";
/**
- * Cache to hold the DateTimePatterns of a Locale.
- */
- private static final ConcurrentMap<Locale, String[]> cachedLocaleData
- = new ConcurrentHashMap<Locale, String[]>(3);
-
- /**
* Cache NumberFormat instances with Locale key.
*/
private static final ConcurrentMap<Locale, NumberFormat> cachedNumberFormatData
@@ -662,33 +656,20 @@
// initialize calendar and related fields
initializeCalendar(loc);
- /* try the cache first */
- String[] dateTimePatterns = cachedLocaleData.get(loc);
- if (dateTimePatterns == null) { /* cache miss */
- LocaleData localeData = LocaleData.get(loc);
- dateTimePatterns = new String[9];
- dateTimePatterns[DateFormat.SHORT + 4] = localeData.getDateFormat(DateFormat.SHORT);
- dateTimePatterns[DateFormat.MEDIUM + 4] = localeData.getDateFormat(DateFormat.MEDIUM);
- dateTimePatterns[DateFormat.LONG + 4] = localeData.getDateFormat(DateFormat.LONG);
- dateTimePatterns[DateFormat.FULL + 4] = localeData.getDateFormat(DateFormat.FULL);
- dateTimePatterns[DateFormat.SHORT] = localeData.getTimeFormat(DateFormat.SHORT);
- dateTimePatterns[DateFormat.MEDIUM] = localeData.getTimeFormat(DateFormat.MEDIUM);
- dateTimePatterns[DateFormat.LONG] = localeData.getTimeFormat(DateFormat.LONG);
- dateTimePatterns[DateFormat.FULL] = localeData.getTimeFormat(DateFormat.FULL);
- dateTimePatterns[8] = "{0} {1}";
- /* update cache */
- cachedLocaleData.putIfAbsent(loc, dateTimePatterns);
- }
formatData = DateFormatSymbols.getInstanceRef(loc);
+ LocaleData localeData = LocaleData.get(loc);
if ((timeStyle >= 0) && (dateStyle >= 0)) {
- Object[] dateTimeArgs = {dateTimePatterns[dateStyle + 4], dateTimePatterns[timeStyle]};
- pattern = MessageFormat.format(dateTimePatterns[8], dateTimeArgs);
+ Object[] dateTimeArgs = {
+ localeData.getDateFormat(dateStyle),
+ localeData.getTimeFormat(timeStyle),
+ };
+ pattern = MessageFormat.format("{0} {1}", dateTimeArgs);
}
else if (timeStyle >= 0) {
- pattern = dateTimePatterns[timeStyle];
+ pattern = localeData.getTimeFormat(timeStyle);
}
else if (dateStyle >= 0) {
- pattern = dateTimePatterns[dateStyle + 4];
+ pattern = localeData.getDateFormat(dateStyle);
}
else {
throw new IllegalArgumentException("No date or time style specified");
diff --git a/ojluni/src/main/java/java/util/Arrays.java b/ojluni/src/main/java/java/util/Arrays.java
index df3f769..0f175c3 100644
--- a/ojluni/src/main/java/java/util/Arrays.java
+++ b/ojluni/src/main/java/java/util/Arrays.java
@@ -26,7 +26,7 @@
package java.util;
-import java.lang.reflect.*;
+import java.lang.reflect.Array;
import java.util.concurrent.ForkJoinPool;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
@@ -80,6 +80,8 @@
*/
public static final int MIN_ARRAY_SORT_GRAN = 1 << 13;
+ // Suppresses default constructor, ensuring non-instantiability.
+ private Arrays() {}
/**
* A comparator that implements the natural ordering of a group of
@@ -104,11 +106,43 @@
static final NaturalOrder INSTANCE = new NaturalOrder();
}
- // Suppresses default constructor, ensuring non-instantiability.
- private Arrays() {}
+ /**
+ * Checks that {@code fromIndex} and {@code toIndex} are in
+ * the range and throws an appropriate exception, if they aren't.
+ */
+ private static void rangeCheck(int length, int fromIndex, int toIndex) {
+ if (fromIndex > toIndex) {
+ throw new IllegalArgumentException(
+ "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
+ }
+ if (fromIndex < 0) {
+ throw new ArrayIndexOutOfBoundsException(fromIndex);
+ }
+ if (toIndex > length) {
+ throw new ArrayIndexOutOfBoundsException(toIndex);
+ }
+ }
+
+ /**
+ * Checks that the range described by {@code offset} and {@code count} doesn't exceed
+ * {@code arrayLength}.
+ *
+ * Android changed.
+ * @hide
+ */
+ public static void checkOffsetAndCount(int arrayLength, int offset, int count) {
+ if ((offset | count) < 0 || offset > arrayLength || arrayLength - offset < count) {
+ throw new ArrayIndexOutOfBoundsException(arrayLength, offset,
+ count);
+ }
+ }
/*
- * Sorting of primitive type arrays.
+ * Sorting methods. Note that all public "sort" methods take the
+ * same form: Performing argument checks if necessary, and then
+ * expanding arguments into those required for the internal
+ * implementation methods residing in other package-private
+ * classes (except for legacyMergeSort, included in this class).
*/
/**
@@ -1167,50 +1201,6 @@
*/
/**
- * Old merge sort implementation can be selected (for
- * compatibility with broken comparators) using a system property.
- * Cannot be a static boolean in the enclosing class due to
- * circular dependencies. To be removed in a future release.
- */
- static final class LegacyMergeSort {
- // Android-changed: Never use circular merge sort.
- private static final boolean userRequested = false;
- }
-
- /*
- * If this platform has an optimizing VM, check whether ComparableTimSort
- * offers any performance benefit over TimSort in conjunction with a
- * comparator that returns:
- * {@code ((Comparable)first).compareTo(Second)}.
- * If not, you are better off deleting ComparableTimSort to
- * eliminate the code duplication. In other words, the commented
- * out code below is the preferable implementation for sorting
- * arrays of Comparables if it offers sufficient performance.
- */
-
-// /**
-// * A comparator that implements the natural ordering of a group of
-// * mutually comparable elements. Using this comparator saves us
-// * from duplicating most of the code in this file (one version for
-// * Comparables, one for explicit Comparators).
-// */
-// private static final Comparator<Object> NATURAL_ORDER =
-// new Comparator<Object>() {
-// @SuppressWarnings("unchecked")
-// public int compare(Object first, Object second) {
-// return ((Comparable<Object>)first).compareTo(second);
-// }
-// };
-//
-// public static void sort(Object[] a) {
-// sort(a, 0, a.length, NATURAL_ORDER);
-// }
-//
-// public static void sort(Object[] a, int fromIndex, int toIndex) {
-// sort(a, fromIndex, toIndex, NATURAL_ORDER);
-// }
-
- /**
* Sorts the specified array of objects into ascending order, according
* to the {@linkplain Comparable natural ordering} of its elements.
* All elements in the array must implement the {@link Comparable}
@@ -1240,7 +1230,7 @@
*
* <p>The implementation was adapted from Tim Peters's list sort for Python
* (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
- * TimSort</a>). It uses techiques from Peter McIlroy's "Optimistic
+ * TimSort</a>). It uses techniques from Peter McIlroy's "Optimistic
* Sorting and Information Theoretic Complexity", in Proceedings of the
* Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
* January 1993.
@@ -1253,18 +1243,13 @@
* {@link Comparable} contract
*/
public static void sort(Object[] a) {
- if (LegacyMergeSort.userRequested)
- legacyMergeSort(a);
- else
+ // Android-changed: LegacyMergeSort is no longer supported
+ // if (LegacyMergeSort.userRequested)
+ // legacyMergeSort(a);
+ // else
ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
}
- /** To be removed in a future release. */
- private static void legacyMergeSort(Object[] a) {
- Object[] aux = a.clone();
- mergeSort(aux, a, 0, a.length, 0);
- }
-
/**
* Sorts the specified range of the specified array of objects into
* ascending order, according to the
@@ -1299,7 +1284,7 @@
*
* <p>The implementation was adapted from Tim Peters's list sort for Python
* (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
- * TimSort</a>). It uses techiques from Peter McIlroy's "Optimistic
+ * TimSort</a>). It uses techniques from Peter McIlroy's "Optimistic
* Sorting and Information Theoretic Complexity", in Proceedings of the
* Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
* January 1993.
@@ -1319,20 +1304,13 @@
*/
public static void sort(Object[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
- if (LegacyMergeSort.userRequested)
- legacyMergeSort(a, fromIndex, toIndex);
- else
+ // Android-changed: LegacyMergeSort is no longer supported
+ // if (LegacyMergeSort.userRequested)
+ // legacyMergeSort(a, fromIndex, toIndex);
+ // else
ComparableTimSort.sort(a, fromIndex, toIndex, null, 0, 0);
}
- /** To be removed in a future release. */
- private static void legacyMergeSort(Object[] a,
- int fromIndex, int toIndex) {
- rangeCheck(a.length, fromIndex, toIndex);
- Object[] aux = copyOfRange(a, fromIndex, toIndex);
- mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
- }
-
/**
* Tuning parameter: list size at or below which insertion sort will be
* used in preference to mergesort.
@@ -1348,6 +1326,7 @@
* off is the offset to generate corresponding low, high in src
* To be removed in a future release.
*/
+ @SuppressWarnings({"unchecked", "rawtypes"})
private static void mergeSort(Object[] src,
Object[] dest,
int low,
@@ -1426,11 +1405,12 @@
*
* <p>The implementation was adapted from Tim Peters's list sort for Python
* (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
- * TimSort</a>). It uses techiques from Peter McIlroy's "Optimistic
+ * TimSort</a>). It uses techniques from Peter McIlroy's "Optimistic
* Sorting and Information Theoretic Complexity", in Proceedings of the
* Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
* January 1993.
*
+ * @param <T> the class of the objects to be sorted
* @param a the array to be sorted
* @param c the comparator to determine the order of the array. A
* {@code null} value indicates that the elements'
@@ -1444,22 +1424,14 @@
if (c == null) {
sort(a);
} else {
- if (LegacyMergeSort.userRequested)
- legacyMergeSort(a, c);
- else
+ // Android-changed: LegacyMergeSort is no longer supported
+ // if (LegacyMergeSort.userRequested)
+ // legacyMergeSort(a, c);
+ // else
TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
}
- /** To be removed in a future release. */
- private static <T> void legacyMergeSort(T[] a, Comparator<? super T> c) {
- T[] aux = a.clone();
- if (c==null)
- mergeSort(aux, a, 0, a.length, 0);
- else
- mergeSort(aux, a, 0, a.length, 0, c);
- }
-
/**
* Sorts the specified range of the specified array of objects according
* to the order induced by the specified comparator. The range to be
@@ -1491,11 +1463,12 @@
*
* <p>The implementation was adapted from Tim Peters's list sort for Python
* (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
- * TimSort</a>). It uses techiques from Peter McIlroy's "Optimistic
+ * TimSort</a>). It uses techniques from Peter McIlroy's "Optimistic
* Sorting and Information Theoretic Complexity", in Proceedings of the
* Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
* January 1993.
*
+ * @param <T> the class of the objects to be sorted
* @param a the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be
* sorted
@@ -1517,89 +1490,14 @@
sort(a, fromIndex, toIndex);
} else {
rangeCheck(a.length, fromIndex, toIndex);
- if (LegacyMergeSort.userRequested)
- legacyMergeSort(a, fromIndex, toIndex, c);
- else
+ // Android-changed: LegacyMergeSort is no longer supported
+ // if (LegacyMergeSort.userRequested)
+ // legacyMergeSort(a, fromIndex, toIndex, c);
+ // else
TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0);
}
}
- /** To be removed in a future release. */
- private static <T> void legacyMergeSort(T[] a, int fromIndex, int toIndex,
- Comparator<? super T> c) {
- rangeCheck(a.length, fromIndex, toIndex);
- T[] aux = copyOfRange(a, fromIndex, toIndex);
- if (c==null)
- mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
- else
- mergeSort(aux, a, fromIndex, toIndex, -fromIndex, c);
- }
-
- /**
- * Src is the source array that starts at index 0
- * Dest is the (possibly larger) array destination with a possible offset
- * low is the index in dest to start sorting
- * high is the end index in dest to end sorting
- * off is the offset into src corresponding to low in dest
- * To be removed in a future release.
- */
- private static void mergeSort(Object[] src,
- Object[] dest,
- int low, int high, int off,
- Comparator c) {
- int length = high - low;
-
- // Insertion sort on smallest arrays
- if (length < INSERTIONSORT_THRESHOLD) {
- for (int i=low; i<high; i++)
- for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--)
- swap(dest, j, j-1);
- return;
- }
-
- // Recursively sort halves of dest into src
- int destLow = low;
- int destHigh = high;
- low += off;
- high += off;
- int mid = (low + high) >>> 1;
- mergeSort(dest, src, low, mid, -off, c);
- mergeSort(dest, src, mid, high, -off, c);
-
- // If list is already sorted, just copy from src to dest. This is an
- // optimization that results in faster sorts for nearly ordered lists.
- if (c.compare(src[mid-1], src[mid]) <= 0) {
- System.arraycopy(src, low, dest, destLow, length);
- return;
- }
-
- // Merge sorted halves (now in src) into dest
- for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
- if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0)
- dest[i] = src[p++];
- else
- dest[i] = src[q++];
- }
- }
-
- /**
- * Checks that {@code fromIndex} and {@code toIndex} are in
- * the range and throws an appropriate exception, if they aren't.
- */
- private static void rangeCheck(int length, int fromIndex, int toIndex) {
- if (fromIndex > toIndex) {
- throw new IllegalArgumentException(
- "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
- }
- if (fromIndex < 0) {
- throw new ArrayIndexOutOfBoundsException(fromIndex);
- }
- if (toIndex > length) {
- throw new ArrayIndexOutOfBoundsException(toIndex);
- }
- }
-
-
// Parallel prefix
/**
@@ -2462,7 +2360,9 @@
while (low <= high) {
int mid = (low + high) >>> 1;
+ @SuppressWarnings("rawtypes")
Comparable midVal = (Comparable)a[mid];
+ @SuppressWarnings("unchecked")
int cmp = midVal.compareTo(key);
if (cmp < 0)
@@ -2486,6 +2386,7 @@
* elements equal to the specified object, there is no guarantee which one
* will be found.
*
+ * @param <T> the class of the objects in the array
* @param a the array to be searched
* @param key the value to be searched for
* @param c the comparator by which the array is ordered. A
@@ -2521,6 +2422,7 @@
* If the range contains multiple elements equal to the specified object,
* there is no guarantee which one will be found.
*
+ * @param <T> the class of the objects in the array
* @param a the array to be searched
* @param fromIndex the index of the first element (inclusive) to be
* searched
@@ -3192,6 +3094,7 @@
* is greater than that of the original array.
* The resulting array is of exactly the same class as the original array.
*
+ * @param <T> the class of the objects in the array
* @param original the array to be copied
* @param newLength the length of the copy to be returned
* @return a copy of the original array, truncated or padded with nulls
@@ -3200,6 +3103,7 @@
* @throws NullPointerException if <tt>original</tt> is null
* @since 1.6
*/
+ @SuppressWarnings("unchecked")
public static <T> T[] copyOf(T[] original, int newLength) {
return (T[]) copyOf(original, newLength, original.getClass());
}
@@ -3214,6 +3118,8 @@
* is greater than that of the original array.
* The resulting array is of the class <tt>newType</tt>.
*
+ * @param <U> the class of the objects in the original array
+ * @param <T> the class of the objects in the returned array
* @param original the array to be copied
* @param newLength the length of the copy to be returned
* @param newType the class of the copy to be returned
@@ -3227,6 +3133,7 @@
* @since 1.6
*/
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
+ @SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
@@ -3443,6 +3350,7 @@
* <p>
* The resulting array is of exactly the same class as the original array.
*
+ * @param <T> the class of the objects in the array
* @param original the array from which a range is to be copied
* @param from the initial index of the range to be copied, inclusive
* @param to the final index of the range to be copied, exclusive.
@@ -3455,8 +3363,9 @@
* @throws NullPointerException if <tt>original</tt> is null
* @since 1.6
*/
+ @SuppressWarnings("unchecked")
public static <T> T[] copyOfRange(T[] original, int from, int to) {
- return copyOfRange(original, from, to, (Class<T[]>) original.getClass());
+ return copyOfRange(original, from, to, (Class<? extends T[]>) original.getClass());
}
/**
@@ -3474,6 +3383,8 @@
* of the returned array will be <tt>to - from</tt>.
* The resulting array is of the class <tt>newType</tt>.
*
+ * @param <U> the class of the objects in the original array
+ * @param <T> the class of the objects in the returned array
* @param original the array from which a range is to be copied
* @param from the initial index of the range to be copied, inclusive
* @param to the final index of the range to be copied, exclusive.
@@ -3494,6 +3405,7 @@
int newLength = to - from;
if (newLength < 0)
throw new IllegalArgumentException(from + " > " + to);
+ @SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
@@ -3805,10 +3717,12 @@
* List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
* </pre>
*
+ * @param <T> the class of the objects in the array
* @param a the array by which the list will be backed
* @return a list view of the specified array
*/
@SafeVarargs
+ @SuppressWarnings("varargs")
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
@@ -3863,12 +3777,13 @@
@Override
public int indexOf(Object o) {
- if (o==null) {
- for (int i=0; i<a.length; i++)
- if (a[i]==null)
+ E[] a = this.a;
+ if (o == null) {
+ for (int i = 0; i < a.length; i++)
+ if (a[i] == null)
return i;
} else {
- for (int i=0; i<a.length; i++)
+ for (int i = 0; i < a.length; i++)
if (o.equals(a[i]))
return i;
}
@@ -3881,6 +3796,11 @@
}
@Override
+ public Spliterator<E> spliterator() {
+ return Spliterators.spliterator(a, Spliterator.ORDERED);
+ }
+
+ @Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
for (E e : a) {
@@ -3898,8 +3818,8 @@
}
@Override
- public Spliterator<E> spliterator() {
- return Spliterators.spliterator(a, Spliterator.ORDERED);
+ public void sort(Comparator<? super E> c) {
+ Arrays.sort(a, c);
}
}
@@ -4192,6 +4112,7 @@
for (Object element : a) {
int elementHash = 0;
+ // Android-changed: getComponentType() is faster than instanceof()
if (element != null) {
Class<?> cl = element.getClass().getComponentType();
if (cl == null)
@@ -4273,6 +4194,7 @@
if (e1 == e2)
continue;
+ // Android-changed: Return early if e2 == null
if (e1 == null || e2 == null)
return false;
@@ -4286,6 +4208,7 @@
}
static boolean deepEquals0(Object e1, Object e2) {
+ // Android-changed: getComponentType() is faster than instanceof()
Class<?> cl1 = e1.getClass().getComponentType();
Class<?> cl2 = e2.getClass().getComponentType();
@@ -4654,7 +4577,7 @@
if (element == null) {
buf.append("null");
} else {
- Class eClass = element.getClass();
+ Class<?> eClass = element.getClass();
if (eClass.isArray()) {
if (eClass == byte[].class)
@@ -4691,6 +4614,7 @@
dejaVu.remove(a);
}
+
/**
* Set all elements of the specified array, using the provided
* generator function to compute each element.
@@ -4846,21 +4770,6 @@
}
/**
- * Checks that the range described by {@code offset} and {@code count} doesn't exceed
- * {@code arrayLength}.
- *
- * Android changed.
- * @hide
- */
- public static void checkOffsetAndCount(int arrayLength, int offset, int count) {
- if ((offset | count) < 0 || offset > arrayLength || arrayLength - offset < count) {
- throw new ArrayIndexOutOfBoundsException(arrayLength, offset,
- count);
- }
- }
-
-
- /**
* Returns a {@link Spliterator} covering all of the specified array.
*
* <p>The spliterator reports {@link Spliterator#SIZED},
@@ -5019,7 +4928,6 @@
Spliterator.ORDERED | Spliterator.IMMUTABLE);
}
-
/**
* Returns a sequential {@link Stream} with the specified array as its
* source.
diff --git a/ojluni/src/main/java/java/util/Collections.java b/ojluni/src/main/java/java/util/Collections.java
index 5a4de2a..65b9b55 100644
--- a/ojluni/src/main/java/java/util/Collections.java
+++ b/ojluni/src/main/java/java/util/Collections.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,8 @@
*/
package java.util;
-
+import java.io.Serializable;
+import java.io.ObjectOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
@@ -35,11 +36,10 @@
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
+import java.util.function.UnaryOperator;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
-import java.util.function.UnaryOperator;
-
/**
* This class consists exclusively of static methods that operate on or return
@@ -162,9 +162,16 @@
* @throws IllegalArgumentException (optional) if the implementation
* detects that the natural ordering of the list elements is
* found to violate the {@link Comparable} contract
+ * @see List#sort(Comparator)
*/
@SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> void sort(List<T> list) {
+ // Android-changed BEGIN: List.sort() is implemented on top of
+ // Collections.sort() rather than the other way around. For backwards
+ // compatibility, Collections.sort() never changes a List's modCount,
+ // but List.sort() implementations may.
+ // was: list.sort(null);
+
if (list.getClass() == ArrayList.class) {
Arrays.sort(((ArrayList) list).elementData, 0, list.size());
return;
@@ -177,6 +184,7 @@
i.next();
i.set((T)a[j]);
}
+ // Android-changed END
}
/**
@@ -231,9 +239,16 @@
* list-iterator does not support the {@code set} operation.
* @throws IllegalArgumentException (optional) if the comparator is
* found to violate the {@link Comparator} contract
+ * @see List#sort(Comparator)
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public static <T> void sort(List<T> list, Comparator<? super T> c) {
+ // Android-changed BEGIN: List.sort() is implemented on top of
+ // Collections.sort() rather than the other way around. For backwards
+ // compatibility, Collections.sort() never changes a List's modCount,
+ // but List.sort() implementations may.
+ // was: list.sort(c);
+
if (list.getClass() == ArrayList.class) {
Arrays.sort(((ArrayList) list).elementData, 0, list.size(), (Comparator) c);
return;
@@ -246,6 +261,7 @@
i.next();
i.set((T)a[j]);
}
+ // Android-changed END
}
@@ -1152,12 +1168,10 @@
public void forEach(Consumer<? super E> action) {
c.forEach(action);
}
-
@Override
public boolean removeIf(Predicate<? super E> filter) {
throw new UnsupportedOperationException();
}
-
@SuppressWarnings("unchecked")
@Override
public Spliterator<E> spliterator() {
@@ -1254,6 +1268,96 @@
}
/**
+ * Returns an unmodifiable view of the specified navigable set. This method
+ * allows modules to provide users with "read-only" access to internal
+ * navigable sets. Query operations on the returned navigable set "read
+ * through" to the specified navigable set. Attempts to modify the returned
+ * navigable set, whether direct, via its iterator, or via its
+ * {@code subSet}, {@code headSet}, or {@code tailSet} views, result in
+ * an {@code UnsupportedOperationException}.<p>
+ *
+ * The returned navigable set will be serializable if the specified
+ * navigable set is serializable.
+ *
+ * @param <T> the class of the objects in the set
+ * @param s the navigable set for which an unmodifiable view is to be
+ * returned
+ * @return an unmodifiable view of the specified navigable set
+ * @since 1.8
+ * @hide
+ */
+ public static <T> NavigableSet<T> unmodifiableNavigableSet(NavigableSet<T> s) {
+ return new UnmodifiableNavigableSet<>(s);
+ }
+
+ /**
+ * Wraps a navigable set and disables all of the mutative operations.
+ *
+ * @param <E> type of elements
+ * @serial include
+ */
+ static class UnmodifiableNavigableSet<E>
+ extends UnmodifiableSortedSet<E>
+ implements NavigableSet<E>, Serializable {
+
+ private static final long serialVersionUID = -6027448201786391929L;
+
+ /**
+ * A singleton empty unmodifiable navigable set used for
+ * {@link #emptyNavigableSet()}.
+ *
+ * @param <E> type of elements, if there were any, and bounds
+ */
+ private static class EmptyNavigableSet<E> extends UnmodifiableNavigableSet<E>
+ implements Serializable {
+ private static final long serialVersionUID = -6291252904449939134L;
+
+ public EmptyNavigableSet() {
+ super(new TreeSet<E>());
+ }
+
+ private Object readResolve() { return EMPTY_NAVIGABLE_SET; }
+ }
+
+ @SuppressWarnings("rawtypes")
+ private static final NavigableSet<?> EMPTY_NAVIGABLE_SET =
+ new EmptyNavigableSet<>();
+
+ /**
+ * The instance we are protecting.
+ */
+ private final NavigableSet<E> ns;
+
+ UnmodifiableNavigableSet(NavigableSet<E> s) {super(s); ns = s;}
+
+ public E lower(E e) { return ns.lower(e); }
+ public E floor(E e) { return ns.floor(e); }
+ public E ceiling(E e) { return ns.ceiling(e); }
+ public E higher(E e) { return ns.higher(e); }
+ public E pollFirst() { throw new UnsupportedOperationException(); }
+ public E pollLast() { throw new UnsupportedOperationException(); }
+ public NavigableSet<E> descendingSet()
+ { return new UnmodifiableNavigableSet<>(ns.descendingSet()); }
+ public Iterator<E> descendingIterator()
+ { return descendingSet().iterator(); }
+
+ public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
+ return new UnmodifiableNavigableSet<>(
+ ns.subSet(fromElement, fromInclusive, toElement, toInclusive));
+ }
+
+ public NavigableSet<E> headSet(E toElement, boolean inclusive) {
+ return new UnmodifiableNavigableSet<>(
+ ns.headSet(toElement, inclusive));
+ }
+
+ public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
+ return new UnmodifiableNavigableSet<>(
+ ns.tailSet(fromElement, inclusive));
+ }
+ }
+
+ /**
* Returns an unmodifiable view of the specified list. This method allows
* modules to provide users with "read-only" access to internal
* lists. Query operations on the returned list "read through" to the
@@ -1307,6 +1411,7 @@
public boolean addAll(int index, Collection<? extends E> c) {
throw new UnsupportedOperationException();
}
+
@Override
public void replaceAll(UnaryOperator<E> operator) {
throw new UnsupportedOperationException();
@@ -1315,6 +1420,7 @@
public void sort(Comparator<? super E> c) {
throw new UnsupportedOperationException();
}
+
public ListIterator<E> listIterator() {return listIterator(0);}
public ListIterator<E> listIterator(final int index) {
@@ -1450,9 +1556,9 @@
throw new UnsupportedOperationException();
}
- private transient Set<K> keySet = null;
- private transient Set<Map.Entry<K,V>> entrySet = null;
- private transient Collection<V> values = null;
+ private transient Set<K> keySet;
+ private transient Set<Map.Entry<K,V>> entrySet;
+ private transient Collection<V> values;
public Set<K> keySet() {
if (keySet==null)
@@ -1521,19 +1627,19 @@
@Override
public V computeIfPresent(K key,
- BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V compute(K key,
- BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V merge(K key, V value,
- BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@@ -1559,7 +1665,6 @@
return e -> action.accept(new UnmodifiableEntry<>(e));
}
- // Override default methods in Collection
public void forEach(Consumer<? super Entry<K, V>> action) {
Objects.requireNonNull(action);
c.forEach(entryConsumer(action));
@@ -1794,6 +1899,149 @@
public K lastKey() { return sm.lastKey(); }
}
+ /**
+ * Returns an unmodifiable view of the specified navigable map. This method
+ * allows modules to provide users with "read-only" access to internal
+ * navigable maps. Query operations on the returned navigable map "read
+ * through" to the specified navigable map. Attempts to modify the returned
+ * navigable map, whether direct, via its collection views, or via its
+ * {@code subMap}, {@code headMap}, or {@code tailMap} views, result in
+ * an {@code UnsupportedOperationException}.<p>
+ *
+ * The returned navigable map will be serializable if the specified
+ * navigable map is serializable.
+ *
+ * @param <K> the class of the map keys
+ * @param <V> the class of the map values
+ * @param m the navigable map for which an unmodifiable view is to be
+ * returned
+ * @return an unmodifiable view of the specified navigable map
+ * @since 1.8
+ * @hide
+ */
+ public static <K,V> NavigableMap<K,V> unmodifiableNavigableMap(NavigableMap<K, ? extends V> m) {
+ return new UnmodifiableNavigableMap<>(m);
+ }
+
+ /**
+ * @serial include
+ */
+ static class UnmodifiableNavigableMap<K,V>
+ extends UnmodifiableSortedMap<K,V>
+ implements NavigableMap<K,V>, Serializable {
+ private static final long serialVersionUID = -4858195264774772197L;
+
+ /**
+ * A class for the {@link EMPTY_NAVIGABLE_MAP} which needs readResolve
+ * to preserve singleton property.
+ *
+ * @param <K> type of keys, if there were any, and of bounds
+ * @param <V> type of values, if there were any
+ */
+ private static class EmptyNavigableMap<K,V> extends UnmodifiableNavigableMap<K,V>
+ implements Serializable {
+
+ private static final long serialVersionUID = -2239321462712562324L;
+
+ EmptyNavigableMap() { super(new TreeMap<K,V>()); }
+
+ @Override
+ public NavigableSet<K> navigableKeySet()
+ { return emptyNavigableSet(); }
+
+ private Object readResolve() { return EMPTY_NAVIGABLE_MAP; }
+ }
+
+ /**
+ * Singleton for {@link emptyNavigableMap()} which is also immutable.
+ */
+ private static final EmptyNavigableMap<?,?> EMPTY_NAVIGABLE_MAP =
+ new EmptyNavigableMap<>();
+
+ /**
+ * The instance we wrap and protect.
+ */
+ private final NavigableMap<K, ? extends V> nm;
+
+ UnmodifiableNavigableMap(NavigableMap<K, ? extends V> m)
+ {super(m); nm = m;}
+
+ public K lowerKey(K key) { return nm.lowerKey(key); }
+ public K floorKey(K key) { return nm.floorKey(key); }
+ public K ceilingKey(K key) { return nm.ceilingKey(key); }
+ public K higherKey(K key) { return nm.higherKey(key); }
+
+ @SuppressWarnings("unchecked")
+ public Entry<K, V> lowerEntry(K key) {
+ Entry<K,V> lower = (Entry<K, V>) nm.lowerEntry(key);
+ return (null != lower)
+ ? new UnmodifiableEntrySet.UnmodifiableEntry<>(lower)
+ : null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Entry<K, V> floorEntry(K key) {
+ Entry<K,V> floor = (Entry<K, V>) nm.floorEntry(key);
+ return (null != floor)
+ ? new UnmodifiableEntrySet.UnmodifiableEntry<>(floor)
+ : null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Entry<K, V> ceilingEntry(K key) {
+ Entry<K,V> ceiling = (Entry<K, V>) nm.ceilingEntry(key);
+ return (null != ceiling)
+ ? new UnmodifiableEntrySet.UnmodifiableEntry<>(ceiling)
+ : null;
+ }
+
+
+ @SuppressWarnings("unchecked")
+ public Entry<K, V> higherEntry(K key) {
+ Entry<K,V> higher = (Entry<K, V>) nm.higherEntry(key);
+ return (null != higher)
+ ? new UnmodifiableEntrySet.UnmodifiableEntry<>(higher)
+ : null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Entry<K, V> firstEntry() {
+ Entry<K,V> first = (Entry<K, V>) nm.firstEntry();
+ return (null != first)
+ ? new UnmodifiableEntrySet.UnmodifiableEntry<>(first)
+ : null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Entry<K, V> lastEntry() {
+ Entry<K,V> last = (Entry<K, V>) nm.lastEntry();
+ return (null != last)
+ ? new UnmodifiableEntrySet.UnmodifiableEntry<>(last)
+ : null;
+ }
+
+ public Entry<K, V> pollFirstEntry()
+ { throw new UnsupportedOperationException(); }
+ public Entry<K, V> pollLastEntry()
+ { throw new UnsupportedOperationException(); }
+ public NavigableMap<K, V> descendingMap()
+ { return unmodifiableNavigableMap(nm.descendingMap()); }
+ public NavigableSet<K> navigableKeySet()
+ { return unmodifiableNavigableSet(nm.navigableKeySet()); }
+ public NavigableSet<K> descendingKeySet()
+ { return unmodifiableNavigableSet(nm.descendingKeySet()); }
+
+ public NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
+ return unmodifiableNavigableMap(
+ nm.subMap(fromKey, fromInclusive, toKey, toInclusive));
+ }
+
+ public NavigableMap<K, V> headMap(K toKey, boolean inclusive)
+ { return unmodifiableNavigableMap(nm.headMap(toKey, inclusive)); }
+ public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive)
+ { return unmodifiableNavigableMap(nm.tailMap(fromKey, inclusive)); }
+ }
+
// Synch Wrappers
/**
@@ -2078,6 +2326,122 @@
}
/**
+ * Returns a synchronized (thread-safe) navigable set backed by the
+ * specified navigable set. In order to guarantee serial access, it is
+ * critical that <strong>all</strong> access to the backing navigable set is
+ * accomplished through the returned navigable set (or its views).<p>
+ *
+ * It is imperative that the user manually synchronize on the returned
+ * navigable set when iterating over it or any of its {@code subSet},
+ * {@code headSet}, or {@code tailSet} views.
+ * <pre>
+ * NavigableSet s = Collections.synchronizedNavigableSet(new TreeSet());
+ * ...
+ * synchronized (s) {
+ * Iterator i = s.iterator(); // Must be in the synchronized block
+ * while (i.hasNext())
+ * foo(i.next());
+ * }
+ * </pre>
+ * or:
+ * <pre>
+ * NavigableSet s = Collections.synchronizedNavigableSet(new TreeSet());
+ * NavigableSet s2 = s.headSet(foo, true);
+ * ...
+ * synchronized (s) { // Note: s, not s2!!!
+ * Iterator i = s2.iterator(); // Must be in the synchronized block
+ * while (i.hasNext())
+ * foo(i.next());
+ * }
+ * </pre>
+ * Failure to follow this advice may result in non-deterministic behavior.
+ *
+ * <p>The returned navigable set will be serializable if the specified
+ * navigable set is serializable.
+ *
+ * @param <T> the class of the objects in the set
+ * @param s the navigable set to be "wrapped" in a synchronized navigable
+ * set
+ * @return a synchronized view of the specified navigable set
+ * @since 1.8
+ * @hide
+ */
+ public static <T> NavigableSet<T> synchronizedNavigableSet(NavigableSet<T> s) {
+ return new SynchronizedNavigableSet<>(s);
+ }
+
+ /**
+ * @serial include
+ */
+ static class SynchronizedNavigableSet<E>
+ extends SynchronizedSortedSet<E>
+ implements NavigableSet<E>
+ {
+ private static final long serialVersionUID = -5505529816273629798L;
+
+ private final NavigableSet<E> ns;
+
+ SynchronizedNavigableSet(NavigableSet<E> s) {
+ super(s);
+ ns = s;
+ }
+
+ SynchronizedNavigableSet(NavigableSet<E> s, Object mutex) {
+ super(s, mutex);
+ ns = s;
+ }
+ public E lower(E e) { synchronized (mutex) {return ns.lower(e);} }
+ public E floor(E e) { synchronized (mutex) {return ns.floor(e);} }
+ public E ceiling(E e) { synchronized (mutex) {return ns.ceiling(e);} }
+ public E higher(E e) { synchronized (mutex) {return ns.higher(e);} }
+ public E pollFirst() { synchronized (mutex) {return ns.pollFirst();} }
+ public E pollLast() { synchronized (mutex) {return ns.pollLast();} }
+
+ public NavigableSet<E> descendingSet() {
+ synchronized (mutex) {
+ return new SynchronizedNavigableSet<>(ns.descendingSet(), mutex);
+ }
+ }
+
+ public Iterator<E> descendingIterator()
+ { synchronized (mutex) { return descendingSet().iterator(); } }
+
+ public NavigableSet<E> subSet(E fromElement, E toElement) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableSet<>(ns.subSet(fromElement, true, toElement, false), mutex);
+ }
+ }
+ public NavigableSet<E> headSet(E toElement) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableSet<>(ns.headSet(toElement, false), mutex);
+ }
+ }
+ public NavigableSet<E> tailSet(E fromElement) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableSet<>(ns.tailSet(fromElement, true), mutex);
+ }
+ }
+
+ public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableSet<>(ns.subSet(fromElement, fromInclusive, toElement, toInclusive), mutex);
+ }
+ }
+
+ public NavigableSet<E> headSet(E toElement, boolean inclusive) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableSet<>(ns.headSet(toElement, inclusive), mutex);
+ }
+ }
+
+ public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableSet<>(ns.tailSet(fromElement, inclusive), mutex);
+ }
+ }
+ }
+
+ /**
* Returns a synchronized (thread-safe) list backed by the specified
* list. In order to guarantee serial access, it is critical that
* <strong>all</strong> access to the backing list is accomplished
@@ -2327,9 +2691,9 @@
synchronized (mutex) {m.clear();}
}
- private transient Set<K> keySet = null;
- private transient Set<Map.Entry<K,V>> entrySet = null;
- private transient Collection<V> values = null;
+ private transient Set<K> keySet;
+ private transient Set<Map.Entry<K,V>> entrySet;
+ private transient Collection<V> values;
public Set<K> keySet() {
synchronized (mutex) {
@@ -2398,22 +2762,22 @@
}
@Override
public V computeIfAbsent(K key,
- Function<? super K, ? extends V> mappingFunction) {
+ Function<? super K, ? extends V> mappingFunction) {
synchronized (mutex) {return m.computeIfAbsent(key, mappingFunction);}
}
@Override
public V computeIfPresent(K key,
- BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
synchronized (mutex) {return m.computeIfPresent(key, remappingFunction);}
}
@Override
public V compute(K key,
- BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
synchronized (mutex) {return m.compute(key, remappingFunction);}
}
@Override
public V merge(K key, V value,
- BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
synchronized (mutex) {return m.merge(key, value, remappingFunction);}
}
@@ -2519,6 +2883,167 @@
}
}
+ /**
+ * Returns a synchronized (thread-safe) navigable map backed by the
+ * specified navigable map. In order to guarantee serial access, it is
+ * critical that <strong>all</strong> access to the backing navigable map is
+ * accomplished through the returned navigable map (or its views).<p>
+ *
+ * It is imperative that the user manually synchronize on the returned
+ * navigable map when iterating over any of its collection views, or the
+ * collections views of any of its {@code subMap}, {@code headMap} or
+ * {@code tailMap} views.
+ * <pre>
+ * NavigableMap m = Collections.synchronizedNavigableMap(new TreeMap());
+ * ...
+ * Set s = m.keySet(); // Needn't be in synchronized block
+ * ...
+ * synchronized (m) { // Synchronizing on m, not s!
+ * Iterator i = s.iterator(); // Must be in synchronized block
+ * while (i.hasNext())
+ * foo(i.next());
+ * }
+ * </pre>
+ * or:
+ * <pre>
+ * NavigableMap m = Collections.synchronizedNavigableMap(new TreeMap());
+ * NavigableMap m2 = m.subMap(foo, true, bar, false);
+ * ...
+ * Set s2 = m2.keySet(); // Needn't be in synchronized block
+ * ...
+ * synchronized (m) { // Synchronizing on m, not m2 or s2!
+ * Iterator i = s.iterator(); // Must be in synchronized block
+ * while (i.hasNext())
+ * foo(i.next());
+ * }
+ * </pre>
+ * Failure to follow this advice may result in non-deterministic behavior.
+ *
+ * <p>The returned navigable map will be serializable if the specified
+ * navigable map is serializable.
+ *
+ * @param <K> the class of the map keys
+ * @param <V> the class of the map values
+ * @param m the navigable map to be "wrapped" in a synchronized navigable
+ * map
+ * @return a synchronized view of the specified navigable map.
+ * @since 1.8
+ * @hide
+ */
+ public static <K,V> NavigableMap<K,V> synchronizedNavigableMap(NavigableMap<K,V> m) {
+ return new SynchronizedNavigableMap<>(m);
+ }
+
+ /**
+ * A synchronized NavigableMap.
+ *
+ * @serial include
+ */
+ static class SynchronizedNavigableMap<K,V>
+ extends SynchronizedSortedMap<K,V>
+ implements NavigableMap<K,V>
+ {
+ private static final long serialVersionUID = 699392247599746807L;
+
+ private final NavigableMap<K,V> nm;
+
+ SynchronizedNavigableMap(NavigableMap<K,V> m) {
+ super(m);
+ nm = m;
+ }
+ SynchronizedNavigableMap(NavigableMap<K,V> m, Object mutex) {
+ super(m, mutex);
+ nm = m;
+ }
+
+ public Entry<K, V> lowerEntry(K key)
+ { synchronized (mutex) { return nm.lowerEntry(key); } }
+ public K lowerKey(K key)
+ { synchronized (mutex) { return nm.lowerKey(key); } }
+ public Entry<K, V> floorEntry(K key)
+ { synchronized (mutex) { return nm.floorEntry(key); } }
+ public K floorKey(K key)
+ { synchronized (mutex) { return nm.floorKey(key); } }
+ public Entry<K, V> ceilingEntry(K key)
+ { synchronized (mutex) { return nm.ceilingEntry(key); } }
+ public K ceilingKey(K key)
+ { synchronized (mutex) { return nm.ceilingKey(key); } }
+ public Entry<K, V> higherEntry(K key)
+ { synchronized (mutex) { return nm.higherEntry(key); } }
+ public K higherKey(K key)
+ { synchronized (mutex) { return nm.higherKey(key); } }
+ public Entry<K, V> firstEntry()
+ { synchronized (mutex) { return nm.firstEntry(); } }
+ public Entry<K, V> lastEntry()
+ { synchronized (mutex) { return nm.lastEntry(); } }
+ public Entry<K, V> pollFirstEntry()
+ { synchronized (mutex) { return nm.pollFirstEntry(); } }
+ public Entry<K, V> pollLastEntry()
+ { synchronized (mutex) { return nm.pollLastEntry(); } }
+
+ public NavigableMap<K, V> descendingMap() {
+ synchronized (mutex) {
+ return
+ new SynchronizedNavigableMap<>(nm.descendingMap(), mutex);
+ }
+ }
+
+ public NavigableSet<K> keySet() {
+ return navigableKeySet();
+ }
+
+ public NavigableSet<K> navigableKeySet() {
+ synchronized (mutex) {
+ return new SynchronizedNavigableSet<>(nm.navigableKeySet(), mutex);
+ }
+ }
+
+ public NavigableSet<K> descendingKeySet() {
+ synchronized (mutex) {
+ return new SynchronizedNavigableSet<>(nm.descendingKeySet(), mutex);
+ }
+ }
+
+
+ public SortedMap<K,V> subMap(K fromKey, K toKey) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableMap<>(
+ nm.subMap(fromKey, true, toKey, false), mutex);
+ }
+ }
+ public SortedMap<K,V> headMap(K toKey) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableMap<>(nm.headMap(toKey, false), mutex);
+ }
+ }
+ public SortedMap<K,V> tailMap(K fromKey) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableMap<>(nm.tailMap(fromKey, true),mutex);
+ }
+ }
+
+ public NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableMap<>(
+ nm.subMap(fromKey, fromInclusive, toKey, toInclusive), mutex);
+ }
+ }
+
+ public NavigableMap<K, V> headMap(K toKey, boolean inclusive) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableMap<>(
+ nm.headMap(toKey, inclusive), mutex);
+ }
+ }
+
+ public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableMap<>(
+ nm.tailMap(fromKey, inclusive), mutex);
+ }
+ }
+ }
+
// Dynamically typesafe collection wrappers
/**
@@ -2601,9 +3126,11 @@
final Collection<E> c;
final Class<E> type;
- void typeCheck(Object o) {
+ @SuppressWarnings("unchecked")
+ E typeCheck(Object o) {
if (o != null && !type.isInstance(o))
throw new ClassCastException(badElementMsg(o));
+ return (E) o;
}
private String badElementMsg(Object o) {
@@ -2612,10 +3139,8 @@
}
CheckedCollection(Collection<E> c, Class<E> type) {
- if (c==null || type == null)
- throw new NullPointerException();
- this.c = c;
- this.type = type;
+ this.c = Objects.requireNonNull(c, "c");
+ this.type = Objects.requireNonNull(type, "type");
}
public int size() { return c.size(); }
@@ -2648,12 +3173,9 @@
// Android-note: Should we delegate to it for forEachRemaining ?
}
- public boolean add(E e) {
- typeCheck(e);
- return c.add(e);
- }
+ public boolean add(E e) { return c.add(typeCheck(e)); }
- private E[] zeroLengthElementArray = null; // Lazily initialized
+ private E[] zeroLengthElementArray; // Lazily initialized
private E[] zeroLengthElementArray() {
return zeroLengthElementArray != null ? zeroLengthElementArray :
@@ -2662,7 +3184,7 @@
@SuppressWarnings("unchecked")
Collection<E> checkedCopyOf(Collection<? extends E> coll) {
- Object[] a = null;
+ Object[] a;
try {
E[] z = zeroLengthElementArray();
a = coll.toArray(z);
@@ -2704,7 +3226,62 @@
public Stream<E> stream() {return c.stream();}
@Override
public Stream<E> parallelStream() {return c.parallelStream();}
+ }
+ /**
+ * Returns a dynamically typesafe view of the specified queue.
+ * Any attempt to insert an element of the wrong type will result in
+ * an immediate {@link ClassCastException}. Assuming a queue contains
+ * no incorrectly typed elements prior to the time a dynamically typesafe
+ * view is generated, and that all subsequent access to the queue
+ * takes place through the view, it is <i>guaranteed</i> that the
+ * queue cannot contain an incorrectly typed element.
+ *
+ * <p>A discussion of the use of dynamically typesafe views may be
+ * found in the documentation for the {@link #checkedCollection
+ * checkedCollection} method.
+ *
+ * <p>The returned queue will be serializable if the specified queue
+ * is serializable.
+ *
+ * <p>Since {@code null} is considered to be a value of any reference
+ * type, the returned queue permits insertion of {@code null} elements
+ * whenever the backing queue does.
+ *
+ * @param <E> the class of the objects in the queue
+ * @param queue the queue for which a dynamically typesafe view is to be
+ * returned
+ * @param type the type of element that {@code queue} is permitted to hold
+ * @return a dynamically typesafe view of the specified queue
+ * @since 1.8
+ * @hide
+ */
+ public static <E> Queue<E> checkedQueue(Queue<E> queue, Class<E> type) {
+ return new CheckedQueue<>(queue, type);
+ }
+
+ /**
+ * @serial include
+ */
+ static class CheckedQueue<E>
+ extends CheckedCollection<E>
+ implements Queue<E>, Serializable
+ {
+ private static final long serialVersionUID = 1433151992604707767L;
+ final Queue<E> queue;
+
+ CheckedQueue(Queue<E> queue, Class<E> elementType) {
+ super(queue, elementType);
+ this.queue = queue;
+ }
+
+ public E element() {return queue.element();}
+ public boolean equals(Object o) {return o == this || c.equals(o);}
+ public int hashCode() {return c.hashCode();}
+ public E peek() {return queue.peek();}
+ public E poll() {return queue.poll();}
+ public E remove() {return queue.remove();}
+ public boolean offer(E e) {return queue.offer(typeCheck(e));}
}
/**
@@ -2815,6 +3392,89 @@
}
}
+/**
+ * Returns a dynamically typesafe view of the specified navigable set.
+ * Any attempt to insert an element of the wrong type will result in an
+ * immediate {@link ClassCastException}. Assuming a navigable set
+ * contains no incorrectly typed elements prior to the time a
+ * dynamically typesafe view is generated, and that all subsequent
+ * access to the navigable set takes place through the view, it is
+ * <em>guaranteed</em> that the navigable set cannot contain an incorrectly
+ * typed element.
+ *
+ * <p>A discussion of the use of dynamically typesafe views may be
+ * found in the documentation for the {@link #checkedCollection
+ * checkedCollection} method.
+ *
+ * <p>The returned navigable set will be serializable if the specified
+ * navigable set is serializable.
+ *
+ * <p>Since {@code null} is considered to be a value of any reference
+ * type, the returned navigable set permits insertion of null elements
+ * whenever the backing sorted set does.
+ *
+ * @param <E> the class of the objects in the set
+ * @param s the navigable set for which a dynamically typesafe view is to be
+ * returned
+ * @param type the type of element that {@code s} is permitted to hold
+ * @return a dynamically typesafe view of the specified navigable set
+ * @since 1.8
+ * @hide
+ */
+ public static <E> NavigableSet<E> checkedNavigableSet(NavigableSet<E> s,
+ Class<E> type) {
+ return new CheckedNavigableSet<>(s, type);
+ }
+
+ /**
+ * @serial include
+ */
+ static class CheckedNavigableSet<E> extends CheckedSortedSet<E>
+ implements NavigableSet<E>, Serializable
+ {
+ private static final long serialVersionUID = -5429120189805438922L;
+
+ private final NavigableSet<E> ns;
+
+ CheckedNavigableSet(NavigableSet<E> s, Class<E> type) {
+ super(s, type);
+ ns = s;
+ }
+
+ public E lower(E e) { return ns.lower(e); }
+ public E floor(E e) { return ns.floor(e); }
+ public E ceiling(E e) { return ns.ceiling(e); }
+ public E higher(E e) { return ns.higher(e); }
+ public E pollFirst() { return ns.pollFirst(); }
+ public E pollLast() {return ns.pollLast(); }
+ public NavigableSet<E> descendingSet()
+ { return checkedNavigableSet(ns.descendingSet(), type); }
+ public Iterator<E> descendingIterator()
+ {return checkedNavigableSet(ns.descendingSet(), type).iterator(); }
+
+ public NavigableSet<E> subSet(E fromElement, E toElement) {
+ return checkedNavigableSet(ns.subSet(fromElement, true, toElement, false), type);
+ }
+ public NavigableSet<E> headSet(E toElement) {
+ return checkedNavigableSet(ns.headSet(toElement, false), type);
+ }
+ public NavigableSet<E> tailSet(E fromElement) {
+ return checkedNavigableSet(ns.tailSet(fromElement, true), type);
+ }
+
+ public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
+ return checkedNavigableSet(ns.subSet(fromElement, fromInclusive, toElement, toInclusive), type);
+ }
+
+ public NavigableSet<E> headSet(E toElement, boolean inclusive) {
+ return checkedNavigableSet(ns.headSet(toElement, inclusive), type);
+ }
+
+ public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
+ return checkedNavigableSet(ns.tailSet(fromElement, inclusive), type);
+ }
+ }
+
/**
* Returns a dynamically typesafe view of the specified list.
* Any attempt to insert an element of the wrong type will result in
@@ -2871,13 +3531,11 @@
public int lastIndexOf(Object o) { return list.lastIndexOf(o); }
public E set(int index, E element) {
- typeCheck(element);
- return list.set(index, element);
+ return list.set(index, typeCheck(element));
}
public void add(int index, E element) {
- typeCheck(element);
- list.add(index, element);
+ list.add(index, typeCheck(element));
}
public boolean addAll(int index, Collection<? extends E> c) {
@@ -2898,13 +3556,11 @@
public void remove() { i.remove(); }
public void set(E e) {
- typeCheck(e);
- i.set(e);
+ i.set(typeCheck(e));
}
public void add(E e) {
- typeCheck(e);
- i.add(e);
+ i.add(typeCheck(e));
}
@Override
@@ -2929,14 +3585,7 @@
@Override
public void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
-
- // Android-changed: Modified from OpenJDK 8 code because typeCheck returns void in
- // OpenJDK 7.
- list.replaceAll(e -> {
- E newValue = operator.apply(e);
- typeCheck(newValue);
- return newValue;
- });
+ list.replaceAll(e -> typeCheck(operator.apply(e)));
}
@Override
@@ -3038,12 +3687,12 @@
private String badKeyMsg(Object key) {
return "Attempt to insert " + key.getClass() +
- " key into map with key type " + keyType;
+ " key into map with key type " + keyType;
}
private String badValueMsg(Object value) {
return "Attempt to insert " + value.getClass() +
- " value into map with value type " + valueType;
+ " value into map with value type " + valueType;
}
CheckedMap(Map<K, V> m, Class<K> keyType, Class<V> valueType) {
@@ -3091,7 +3740,7 @@
m.put(e.getKey(), e.getValue());
}
- private transient Set<Map.Entry<K,V>> entrySet = null;
+ private transient Set<Map.Entry<K,V>> entrySet;
public Set<Map.Entry<K,V>> entrySet() {
if (entrySet==null)
@@ -3434,6 +4083,178 @@
}
}
+ /**
+ * Returns a dynamically typesafe view of the specified navigable map.
+ * Any attempt to insert a mapping whose key or value have the wrong
+ * type will result in an immediate {@link ClassCastException}.
+ * Similarly, any attempt to modify the value currently associated with
+ * a key will result in an immediate {@link ClassCastException},
+ * whether the modification is attempted directly through the map
+ * itself, or through a {@link Map.Entry} instance obtained from the
+ * map's {@link Map#entrySet() entry set} view.
+ *
+ * <p>Assuming a map contains no incorrectly typed keys or values
+ * prior to the time a dynamically typesafe view is generated, and
+ * that all subsequent access to the map takes place through the view
+ * (or one of its collection views), it is <em>guaranteed</em> that the
+ * map cannot contain an incorrectly typed key or value.
+ *
+ * <p>A discussion of the use of dynamically typesafe views may be
+ * found in the documentation for the {@link #checkedCollection
+ * checkedCollection} method.
+ *
+ * <p>The returned map will be serializable if the specified map is
+ * serializable.
+ *
+ * <p>Since {@code null} is considered to be a value of any reference
+ * type, the returned map permits insertion of null keys or values
+ * whenever the backing map does.
+ *
+ * @param <K> type of map keys
+ * @param <V> type of map values
+ * @param m the map for which a dynamically typesafe view is to be
+ * returned
+ * @param keyType the type of key that {@code m} is permitted to hold
+ * @param valueType the type of value that {@code m} is permitted to hold
+ * @return a dynamically typesafe view of the specified map
+ * @since 1.8
+ * @hide
+ */
+ public static <K,V> NavigableMap<K,V> checkedNavigableMap(NavigableMap<K, V> m,
+ Class<K> keyType,
+ Class<V> valueType) {
+ return new CheckedNavigableMap<>(m, keyType, valueType);
+ }
+
+ /**
+ * @serial include
+ */
+ static class CheckedNavigableMap<K,V> extends CheckedSortedMap<K,V>
+ implements NavigableMap<K,V>, Serializable
+ {
+ private static final long serialVersionUID = -4852462692372534096L;
+
+ private final NavigableMap<K, V> nm;
+
+ CheckedNavigableMap(NavigableMap<K, V> m,
+ Class<K> keyType, Class<V> valueType) {
+ super(m, keyType, valueType);
+ nm = m;
+ }
+
+ public Comparator<? super K> comparator() { return nm.comparator(); }
+ public K firstKey() { return nm.firstKey(); }
+ public K lastKey() { return nm.lastKey(); }
+
+ public Entry<K, V> lowerEntry(K key) {
+ Entry<K,V> lower = nm.lowerEntry(key);
+ return (null != lower)
+ ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(lower, valueType)
+ : null;
+ }
+
+ public K lowerKey(K key) { return nm.lowerKey(key); }
+
+ public Entry<K, V> floorEntry(K key) {
+ Entry<K,V> floor = nm.floorEntry(key);
+ return (null != floor)
+ ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(floor, valueType)
+ : null;
+ }
+
+ public K floorKey(K key) { return nm.floorKey(key); }
+
+ public Entry<K, V> ceilingEntry(K key) {
+ Entry<K,V> ceiling = nm.ceilingEntry(key);
+ return (null != ceiling)
+ ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(ceiling, valueType)
+ : null;
+ }
+
+ public K ceilingKey(K key) { return nm.ceilingKey(key); }
+
+ public Entry<K, V> higherEntry(K key) {
+ Entry<K,V> higher = nm.higherEntry(key);
+ return (null != higher)
+ ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(higher, valueType)
+ : null;
+ }
+
+ public K higherKey(K key) { return nm.higherKey(key); }
+
+ public Entry<K, V> firstEntry() {
+ Entry<K,V> first = nm.firstEntry();
+ return (null != first)
+ ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(first, valueType)
+ : null;
+ }
+
+ public Entry<K, V> lastEntry() {
+ Entry<K,V> last = nm.lastEntry();
+ return (null != last)
+ ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(last, valueType)
+ : null;
+ }
+
+ public Entry<K, V> pollFirstEntry() {
+ Entry<K,V> entry = nm.pollFirstEntry();
+ return (null == entry)
+ ? null
+ : new CheckedMap.CheckedEntrySet.CheckedEntry<>(entry, valueType);
+ }
+
+ public Entry<K, V> pollLastEntry() {
+ Entry<K,V> entry = nm.pollLastEntry();
+ return (null == entry)
+ ? null
+ : new CheckedMap.CheckedEntrySet.CheckedEntry<>(entry, valueType);
+ }
+
+ public NavigableMap<K, V> descendingMap() {
+ return checkedNavigableMap(nm.descendingMap(), keyType, valueType);
+ }
+
+ public NavigableSet<K> keySet() {
+ return navigableKeySet();
+ }
+
+ public NavigableSet<K> navigableKeySet() {
+ return checkedNavigableSet(nm.navigableKeySet(), keyType);
+ }
+
+ public NavigableSet<K> descendingKeySet() {
+ return checkedNavigableSet(nm.descendingKeySet(), keyType);
+ }
+
+ @Override
+ public NavigableMap<K,V> subMap(K fromKey, K toKey) {
+ return checkedNavigableMap(nm.subMap(fromKey, true, toKey, false),
+ keyType, valueType);
+ }
+
+ @Override
+ public NavigableMap<K,V> headMap(K toKey) {
+ return checkedNavigableMap(nm.headMap(toKey, false), keyType, valueType);
+ }
+
+ @Override
+ public NavigableMap<K,V> tailMap(K fromKey) {
+ return checkedNavigableMap(nm.tailMap(fromKey, true), keyType, valueType);
+ }
+
+ public NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
+ return checkedNavigableMap(nm.subMap(fromKey, fromInclusive, toKey, toInclusive), keyType, valueType);
+ }
+
+ public NavigableMap<K, V> headMap(K toKey, boolean inclusive) {
+ return checkedNavigableMap(nm.headMap(toKey, inclusive), keyType, valueType);
+ }
+
+ public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) {
+ return checkedNavigableMap(nm.tailMap(fromKey, inclusive), keyType, valueType);
+ }
+ }
+
// Empty collections
/**
@@ -3623,7 +4444,50 @@
private Object readResolve() {
return EMPTY_SET;
}
+ }
+ /**
+ * Returns an empty sorted set (immutable). This set is serializable.
+ *
+ * <p>This example illustrates the type-safe way to obtain an empty
+ * sorted set:
+ * <pre> {@code
+ * SortedSet<String> s = Collections.emptySortedSet();
+ * }</pre>
+ *
+ * @implNote Implementations of this method need not create a separate
+ * {@code SortedSet} object for each call.
+ *
+ * @param <E> type of elements, if there were any, in the set
+ * @return the empty sorted set
+ * @since 1.8
+ * @hide
+ */
+ @SuppressWarnings("unchecked")
+ public static <E> SortedSet<E> emptySortedSet() {
+ return (SortedSet<E>) UnmodifiableNavigableSet.EMPTY_NAVIGABLE_SET;
+ }
+
+ /**
+ * Returns an empty navigable set (immutable). This set is serializable.
+ *
+ * <p>This example illustrates the type-safe way to obtain an empty
+ * navigable set:
+ * <pre> {@code
+ * NavigableSet<String> s = Collections.emptyNavigableSet();
+ * }</pre>
+ *
+ * @implNote Implementations of this method need not
+ * create a separate {@code NavigableSet} object for each call.
+ *
+ * @param <E> type of elements, if there were any, in the set
+ * @return the empty navigable set
+ * @since 1.8
+ * @hide
+ */
+ @SuppressWarnings("unchecked")
+ public static <E> NavigableSet<E> emptyNavigableSet() {
+ return (NavigableSet<E>) UnmodifiableNavigableSet.EMPTY_NAVIGABLE_SET;
}
/**
@@ -3641,10 +4505,12 @@
* <pre>
* List<String> s = Collections.emptyList();
* </pre>
- * Implementation note: Implementations of this method need not
- * create a separate <tt>List</tt> object for each call. Using this
- * method is likely to have comparable cost to using the like-named
- * field. (Unlike this method, the field does not provide type safety.)
+ *
+ * @implNote
+ * Implementations of this method need not create a separate <tt>List</tt>
+ * object for each call. Using this method is likely to have comparable
+ * cost to using the like-named field. (Unlike this method, the field does
+ * not provide type safety.)
*
* @param <T> type of elements, if there were any, in the list
* @return an empty immutable list
@@ -3701,6 +4567,13 @@
Objects.requireNonNull(filter);
return false;
}
+ @Override
+ public void replaceAll(UnaryOperator<E> operator) {
+ Objects.requireNonNull(operator);
+ }
+ @Override
+ public void sort(Comparator<? super E> c) {
+ }
// Override default methods in Collection
@Override
@@ -3711,15 +4584,6 @@
@Override
public Spliterator<E> spliterator() { return Spliterators.emptySpliterator(); }
- @Override
- public void replaceAll(UnaryOperator<E> operator) {
- Objects.requireNonNull(operator);
- }
- @Override
- public void sort(Comparator<? super E> c) {
- }
-
-
// Preserves singleton property
private Object readResolve() {
return EMPTY_LIST;
@@ -3759,6 +4623,50 @@
}
/**
+ * Returns an empty sorted map (immutable). This map is serializable.
+ *
+ * <p>This example illustrates the type-safe way to obtain an empty map:
+ * <pre> {@code
+ * SortedMap<String, Date> s = Collections.emptySortedMap();
+ * }</pre>
+ *
+ * @implNote Implementations of this method need not create a separate
+ * {@code SortedMap} object for each call.
+ *
+ * @param <K> the class of the map keys
+ * @param <V> the class of the map values
+ * @return an empty sorted map
+ * @since 1.8
+ * @hide
+ */
+ @SuppressWarnings("unchecked")
+ public static final <K,V> SortedMap<K,V> emptySortedMap() {
+ return (SortedMap<K,V>) UnmodifiableNavigableMap.EMPTY_NAVIGABLE_MAP;
+ }
+
+ /**
+ * Returns an empty navigable map (immutable). This map is serializable.
+ *
+ * <p>This example illustrates the type-safe way to obtain an empty map:
+ * <pre> {@code
+ * NavigableMap<String, Date> s = Collections.emptyNavigableMap();
+ * }</pre>
+ *
+ * @implNote Implementations of this method need not create a separate
+ * {@code NavigableMap} object for each call.
+ *
+ * @param <K> the class of the map keys
+ * @param <V> the class of the map values
+ * @return an empty navigable map
+ * @since 1.8
+ * @hide
+ */
+ @SuppressWarnings("unchecked")
+ public static final <K,V> NavigableMap<K,V> emptyNavigableMap() {
+ return (NavigableMap<K,V>) UnmodifiableNavigableMap.EMPTY_NAVIGABLE_MAP;
+ }
+
+ /**
* @serial include
*/
private static class EmptyMap<K,V>
@@ -3821,25 +4729,25 @@
@Override
public V computeIfAbsent(K key,
- Function<? super K, ? extends V> mappingFunction) {
+ Function<? super K, ? extends V> mappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V computeIfPresent(K key,
- BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V compute(K key,
- BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V merge(K key, V value,
- BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@@ -4022,15 +4930,16 @@
throw new UnsupportedOperationException();
}
@Override
- public Spliterator<E> spliterator() {
- return singletonSpliterator(element);
- }
public void replaceAll(UnaryOperator<E> operator) {
throw new UnsupportedOperationException();
}
@Override
public void sort(Comparator<? super E> c) {
}
+ @Override
+ public Spliterator<E> spliterator() {
+ return singletonSpliterator(element);
+ }
}
/**
@@ -4065,19 +4974,15 @@
v = value;
}
- public int size() {return 1;}
+ public int size() {return 1;}
+ public boolean isEmpty() {return false;}
+ public boolean containsKey(Object key) {return eq(key, k);}
+ public boolean containsValue(Object value) {return eq(value, v);}
+ public V get(Object key) {return (eq(key, k) ? v : null);}
- public boolean isEmpty() {return false;}
-
- public boolean containsKey(Object key) {return eq(key, k);}
-
- public boolean containsValue(Object value) {return eq(value, v);}
-
- public V get(Object key) {return (eq(key, k) ? v : null);}
-
- private transient Set<K> keySet = null;
- private transient Set<Map.Entry<K,V>> entrySet = null;
- private transient Collection<V> values = null;
+ private transient Set<K> keySet;
+ private transient Set<Map.Entry<K,V>> entrySet;
+ private transient Collection<V> values;
public Set<K> keySet() {
if (keySet==null)
@@ -4136,25 +5041,25 @@
@Override
public V computeIfAbsent(K key,
- Function<? super K, ? extends V> mappingFunction) {
+ Function<? super K, ? extends V> mappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V computeIfPresent(K key,
- BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V compute(K key,
- BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V merge(K key, V value,
- BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
}
@@ -4753,7 +5658,6 @@
public boolean removeIf(Predicate<? super E> filter) {
return q.removeIf(filter);
}
-
@Override
public Spliterator<E> spliterator() {return q.spliterator();}
@Override
diff --git a/ojluni/src/main/java/sun/security/action/PutAllAction.java b/ojluni/src/main/java/sun/security/action/PutAllAction.java
deleted file mode 100644
index b58da23..0000000
--- a/ojluni/src/main/java/sun/security/action/PutAllAction.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.action;
-
-import java.util.Map;
-
-import java.security.Provider;
-import java.security.PrivilegedAction;
-
-/**
- * A convenience PrivilegedAction class for setting the properties of
- * a provider. See the SunRsaSign provider for a usage example.
- *
- * @see sun.security.rsa.SunRsaSign
- * @author Andreas Sterbenz
- * @since 1.5
- */
-public class PutAllAction implements PrivilegedAction<Void> {
-
- private final Provider provider;
- private final Map map;
-
- public PutAllAction(Provider provider, Map map) {
- this.provider = provider;
- this.map = map;
- }
-
- public Void run() {
- provider.putAll(map);
- return null;
- }
-
-}
diff --git a/ojluni/src/main/native/Inet4AddressImpl.c b/ojluni/src/main/native/Inet4AddressImpl.c
deleted file mode 100644
index fce6d95..0000000
--- a/ojluni/src/main/native/Inet4AddressImpl.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <errno.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-#ifdef _ALLBSD_SOURCE
-#include <unistd.h>
-#include <sys/param.h>
-#endif
-
-#include "jvm.h"
-#include "jni_util.h"
-#include "net_util.h"
-
-#include "JNIHelp.h"
-
-#define NATIVE_METHOD(className, functionName, signature) \
-{ #functionName, signature, (void*)(className ## _ ## functionName) }
-
-//#if defined(__GLIBC__) || (defined(__FreeBSD__) && (__FreeBSD_version >= 601104))
-#define HAS_GLIBC_GETHOSTBY_R 1
-//#endif
-
-#define SET_NONBLOCKING(fd) { \
- int flags = fcntl(fd, F_GETFL); \
- flags |= O_NONBLOCK; \
- fcntl(fd, F_SETFL, flags); \
-}
-
-/**
- * ping implementation.
- * Send a ICMP_ECHO_REQUEST packet every second until either the timeout
- * expires or a answer is received.
- * Returns true is an ECHO_REPLY is received, otherwise, false.
- */
-static jboolean
-ping4(JNIEnv *env, jint fd, struct sockaddr_in* him, jint timeout,
- struct sockaddr_in* netif, jint ttl) {
- jint size;
- jint n, hlen1, icmplen;
- socklen_t len;
- char sendbuf[1500];
- char recvbuf[1500];
- struct icmp *icmp;
- struct ip *ip;
- struct sockaddr_in sa_recv;
- jchar pid;
- jint tmout2, seq = 1;
- struct timeval tv;
- size_t plen;
-
- /* icmp_id is a 16 bit data type, therefore down cast the pid */
- pid = (jchar)getpid();
- size = 60*1024;
- setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
- /*
- * sets the ttl (max number of hops)
- */
- if (ttl > 0) {
- setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
- }
- /*
- * a specific interface was specified, so let's bind the socket
- * to that interface to ensure the requests are sent only through it.
- */
- if (netif != NULL) {
- if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in)) < 0) {
- NET_ThrowNew(env, errno, "Can't bind socket");
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
- }
- /*
- * Make the socket non blocking so we can use select
- */
- SET_NONBLOCKING(fd);
- do {
- /*
- * create the ICMP request
- */
- icmp = (struct icmp *) sendbuf;
- icmp->icmp_type = ICMP_ECHO;
- icmp->icmp_code = 0;
- icmp->icmp_id = htons(pid);
- icmp->icmp_seq = htons(seq);
- seq++;
- gettimeofday(&tv, NULL);
- memcpy(icmp->icmp_data, &tv, sizeof(tv));
- plen = ICMP_ADVLENMIN + sizeof(tv);
- icmp->icmp_cksum = 0;
- icmp->icmp_cksum = in_cksum((u_short *)icmp, plen);
- /*
- * send it
- */
- n = sendto(fd, sendbuf, plen, 0, (struct sockaddr *)him,
- sizeof(struct sockaddr));
- if (n < 0 && errno != EINPROGRESS ) {
-#ifdef __linux__
- if (errno != EINVAL && errno != EHOSTUNREACH)
- /*
- * On some Linux versions, when a socket is bound to the loopback
- * interface, sendto will fail and errno will be set to
- * EINVAL or EHOSTUNREACH. When that happens, don't throw an
- * exception, just return false.
- */
-#endif /*__linux__ */
- NET_ThrowNew(env, errno, "Can't send ICMP packet");
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
-
- tmout2 = timeout > 1000 ? 1000 : timeout;
- do {
- tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2);
- if (tmout2 >= 0) {
- len = sizeof(sa_recv);
- n = recvfrom(fd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr *)&sa_recv, &len);
- ip = (struct ip*) recvbuf;
- hlen1 = (ip->ip_hl) << 2;
- icmp = (struct icmp *) (recvbuf + hlen1);
- icmplen = n - hlen1;
- /*
- * We did receive something, but is it what we were expecting?
- * I.E.: A ICMP_ECHOREPLY packet with the proper PID.
- */
- if (icmplen >= 8 && icmp->icmp_type == ICMP_ECHOREPLY
- && (ntohs(icmp->icmp_id) == pid)) {
- if ((him->sin_addr.s_addr == sa_recv.sin_addr.s_addr)) {
- untagSocket(env, fd);
- close(fd);
- return JNI_TRUE;
- }
-
- if (him->sin_addr.s_addr == 0) {
- untagSocket(env, fd);
- close(fd);
- return JNI_TRUE;
- }
- }
-
- }
- } while (tmout2 > 0);
- timeout -= 1000;
- } while (timeout >0);
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
-}
-
-/*
- * Class: java_net_Inet4AddressImpl
- * Method: isReachable0
- * Signature: ([bI[bI)Z
- */
-JNIEXPORT jboolean JNICALL
-Inet4AddressImpl_isReachable0(JNIEnv *env, jobject this,
- jbyteArray addrArray,
- jint timeout,
- jbyteArray ifArray,
- jint ttl) {
- jint addr;
- jbyte caddr[4];
- jint fd;
- struct sockaddr_in him;
- struct sockaddr_in* netif = NULL;
- struct sockaddr_in inf;
- int len = 0;
- int connect_rv = -1;
- int sz;
-
- memset((char *) caddr, 0, sizeof(caddr));
- memset((char *) &him, 0, sizeof(him));
- memset((char *) &inf, 0, sizeof(inf));
- sz = (*env)->GetArrayLength(env, addrArray);
- if (sz != 4) {
- return JNI_FALSE;
- }
- (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
- addr = ((caddr[0]<<24) & 0xff000000);
- addr |= ((caddr[1] <<16) & 0xff0000);
- addr |= ((caddr[2] <<8) & 0xff00);
- addr |= (caddr[3] & 0xff);
- addr = htonl(addr);
- him.sin_addr.s_addr = addr;
- him.sin_family = AF_INET;
- len = sizeof(him);
- /*
- * If a network interface was specified, let's create the address
- * for it.
- */
- if (!(IS_NULL(ifArray))) {
- memset((char *) caddr, 0, sizeof(caddr));
- (*env)->GetByteArrayRegion(env, ifArray, 0, 4, caddr);
- addr = ((caddr[0]<<24) & 0xff000000);
- addr |= ((caddr[1] <<16) & 0xff0000);
- addr |= ((caddr[2] <<8) & 0xff00);
- addr |= (caddr[3] & 0xff);
- addr = htonl(addr);
- inf.sin_addr.s_addr = addr;
- inf.sin_family = AF_INET;
- inf.sin_port = 0;
- netif = &inf;
- }
-
- /*
- * Let's try to create a RAW socket to send ICMP packets
- * This usually requires "root" privileges, so it's likely to fail.
- */
- fd = JVM_Socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
- if (fd != -1) {
- /*
- * It didn't fail, so we can use ICMP_ECHO requests.
- */
- tagSocket(env, fd);
- return ping4(env, fd, &him, timeout, netif, ttl);
- }
-
- /*
- * Can't create a raw socket, so let's try a TCP socket
- */
- fd = JVM_Socket(AF_INET, SOCK_STREAM, 0);
- if (fd == JVM_IO_ERR) {
- /* note: if you run out of fds, you may not be able to load
- * the exception class, and get a NoClassDefFoundError
- * instead.
- */
- NET_ThrowNew(env, errno, "Can't create socket");
- return JNI_FALSE;
- }
- tagSocket(env, fd);
-
- if (ttl > 0) {
- setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
- }
-
- /*
- * A network interface was specified, so let's bind to it.
- */
- if (netif != NULL) {
- if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in)) < 0) {
- NET_ThrowNew(env, errno, "Can't bind socket");
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
- }
-
- /*
- * Make the socket non blocking so we can use select/poll.
- */
- SET_NONBLOCKING(fd);
-
- /* no need to use NET_Connect as non-blocking */
- him.sin_port = htons(7); /* Echo */
- connect_rv = JVM_Connect(fd, (struct sockaddr *)&him, len);
-
- /**
- * connection established or refused immediately, either way it means
- * we were able to reach the host!
- */
- if (connect_rv == 0 || errno == ECONNREFUSED) {
- untagSocket(env, fd);
- close(fd);
- return JNI_TRUE;
- } else {
- int optlen;
-
- switch (errno) {
- case ENETUNREACH: /* Network Unreachable */
- case EAFNOSUPPORT: /* Address Family not supported */
- case EADDRNOTAVAIL: /* address is not available on the remote machine */
-#ifdef __linux__
- case EINVAL:
- case EHOSTUNREACH:
- /*
- * On some Linux versions, when a socket is bound to the loopback
- * interface, connect will fail and errno will be set to EINVAL
- * or EHOSTUNREACH. When that happens, don't throw an exception,
- * just return false.
- */
-#endif /* __linux__ */
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
-
- if (errno != EINPROGRESS) {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
- "connect failed");
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
-
- timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout);
- if (timeout >= 0) {
- /* has connection been established? */
- optlen = sizeof(connect_rv);
- if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
- &optlen) <0) {
- connect_rv = errno;
- }
- if (connect_rv == 0 || connect_rv == ECONNREFUSED) {
- untagSocket(env, fd);
- close(fd);
- return JNI_TRUE;
- }
- }
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
-}
diff --git a/ojluni/src/main/native/Inet6AddressImpl.c b/ojluni/src/main/native/Inet6AddressImpl.c
index 85f2314..8129d4a 100644
--- a/ojluni/src/main/native/Inet6AddressImpl.c
+++ b/ojluni/src/main/native/Inet6AddressImpl.c
@@ -44,7 +44,6 @@
#include <netinet/icmp6.h>
#endif
-#include "java_net_Inet4AddressImpl.h"
#include "JNIHelp.h"
#define NATIVE_METHOD(className, functionName, signature) \
@@ -137,296 +136,7 @@
fcntl(fd, F_SETFL, flags); \
}
-#ifdef AF_INET6
-static jboolean
-ping6(JNIEnv *env, jint fd, struct sockaddr_in6* him, jint timeout,
- struct sockaddr_in6* netif, jint ttl) {
- jint size;
- jint n;
- socklen_t len;
- char sendbuf[1500];
- unsigned char recvbuf[1500];
- struct icmp6_hdr *icmp6;
- struct sockaddr_in6 sa_recv;
- jbyte *caddr, *recv_caddr;
- jchar pid;
- jint tmout2, seq = 1;
- struct timeval tv;
- size_t plen;
-
-#ifdef __linux__
- {
- int csum_offset;
- /**
- * For some strange reason, the linux kernel won't calculate the
- * checksum of ICMPv6 packets unless you set this socket option
- */
- csum_offset = 2;
- setsockopt(fd, SOL_RAW, IPV6_CHECKSUM, &csum_offset, sizeof(int));
- }
-#endif
-
- caddr = (jbyte *)&(him->sin6_addr);
-
- /* icmp_id is a 16 bit data type, therefore down cast the pid */
- pid = (jchar)getpid();
- size = 60*1024;
- setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
- if (ttl > 0) {
- setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
- }
- if (netif != NULL) {
- if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) {
- NET_ThrowNew(env, errno, "Can't bind socket");
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
- }
- SET_NONBLOCKING(fd);
-
- do {
- icmp6 = (struct icmp6_hdr *) sendbuf;
- icmp6->icmp6_type = ICMP6_ECHO_REQUEST;
- icmp6->icmp6_code = 0;
- /* let's tag the ECHO packet with our pid so we can identify it */
- icmp6->icmp6_id = htons(pid);
- icmp6->icmp6_seq = htons(seq);
- seq++;
- icmp6->icmp6_cksum = 0;
- gettimeofday(&tv, NULL);
- memcpy(sendbuf + sizeof(struct icmp6_hdr), &tv, sizeof(tv));
- plen = sizeof(struct icmp6_hdr) + sizeof(tv);
- n = sendto(fd, sendbuf, plen, 0, (struct sockaddr*) him, sizeof(struct sockaddr_in6));
- if (n < 0 && errno != EINPROGRESS) {
-#ifdef __linux__
- if (errno != EINVAL && errno != EHOSTUNREACH)
- /*
- * On some Linux versions, when a socket is bound to the
- * loopback interface, sendto will fail and errno will be
- * set to EINVAL or EHOSTUNREACH.
- * When that happens, don't throw an exception, just return false.
- */
-#endif /*__linux__ */
- NET_ThrowNew(env, errno, "Can't send ICMP packet");
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
-
- tmout2 = timeout > 1000 ? 1000 : timeout;
- do {
- tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2);
-
- if (tmout2 >= 0) {
- len = sizeof(sa_recv);
- n = recvfrom(fd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*) &sa_recv, &len);
- icmp6 = (struct icmp6_hdr *) (recvbuf);
- recv_caddr = (jbyte *)&(sa_recv.sin6_addr);
- /*
- * We did receive something, but is it what we were expecting?
- * I.E.: An ICMP6_ECHO_REPLY packet with the proper PID and
- * from the host that we are trying to determine is reachable.
- */
- if (n >= 8 && icmp6->icmp6_type == ICMP6_ECHO_REPLY &&
- (ntohs(icmp6->icmp6_id) == pid)) {
- if (NET_IsEqual(caddr, recv_caddr)) {
- untagSocket(env, fd);
- close(fd);
- return JNI_TRUE;
- }
- if (NET_IsZeroAddr(caddr)) {
- untagSocket(env, fd);
- close(fd);
- return JNI_TRUE;
- }
- }
- }
- } while (tmout2 > 0);
- timeout -= 1000;
- } while (timeout > 0);
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
-}
-#endif /* AF_INET6 */
-
-/*
- * Class: java_net_Inet6AddressImpl
- * Method: isReachable0
- * Signature: ([bII[bI)Z
- */
-JNIEXPORT jboolean JNICALL
-Inet6AddressImpl_isReachable0(JNIEnv *env, jobject this,
- jbyteArray addrArray,
- jint scope,
- jint timeout,
- jbyteArray ifArray,
- jint ttl, jint if_scope) {
-#ifdef AF_INET6
- jbyte caddr[16];
- jint fd, sz;
- struct sockaddr_in6 him6;
- struct sockaddr_in6 inf6;
- struct sockaddr_in6* netif = NULL;
- int len = 0;
- int connect_rv = -1;
-
- /*
- * If IPv6 is not enable, then we can't reach an IPv6 address, can we?
- */
- if (!ipv6_available()) {
- return JNI_FALSE;
- }
- /*
- * If it's an IPv4 address, ICMP won't work with IPv4 mapped address,
- * therefore, let's delegate to the Inet4Address method.
- */
- sz = (*env)->GetArrayLength(env, addrArray);
- if (sz == 4) {
- return Inet4AddressImpl_isReachable0(env, this,
- addrArray,
- timeout,
- ifArray, ttl);
- }
-
- memset((void *) caddr, 0, 16);
- memset((void *) &him6, 0, sizeof(him6));
- (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
- memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
- him6.sin6_family = AF_INET6;
-
- // Android-change: Don't try and figure out a default scope ID if one isn't
- // set. It's only useful for link local addresses anyway, and callers are
- // expected to call isReachable with a specific NetworkInterface if they
- // want to query the reachability of an address that's local to that IF.
- if (scope > 0)
- him6.sin6_scope_id = scope;
- len = sizeof(struct sockaddr_in6);
- /*
- * If a network interface was specified, let's create the address
- * for it.
- */
- if (!(IS_NULL(ifArray))) {
- memset((void *) caddr, 0, 16);
- memset((void *) &inf6, 0, sizeof(inf6));
- (*env)->GetByteArrayRegion(env, ifArray, 0, 16, caddr);
- memcpy((void *)&(inf6.sin6_addr), caddr, sizeof(struct in6_addr) );
- inf6.sin6_family = AF_INET6;
- inf6.sin6_scope_id = if_scope;
- netif = &inf6;
- }
- /*
- * If we can create a RAW socket, then when can use the ICMP ECHO_REQUEST
- * otherwise we'll try a tcp socket to the Echo port (7).
- * Note that this is empiric, and not connecting could mean it's blocked
- * or the echo service has been disabled.
- */
-
- fd = JVM_Socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
-
- if (fd != -1) { /* Good to go, let's do a ping */
- tagSocket(env, fd);
- return ping6(env, fd, &him6, timeout, netif, ttl);
- }
-
- /* No good, let's fall back on TCP */
- fd = JVM_Socket(AF_INET6, SOCK_STREAM, 0);
- if (fd == JVM_IO_ERR) {
- /* note: if you run out of fds, you may not be able to load
- * the exception class, and get a NoClassDefFoundError
- * instead.
- */
- NET_ThrowNew(env, errno, "Can't create socket");
- return JNI_FALSE;
- }
- tagSocket(env, fd);
-
- if (ttl > 0) {
- setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
- }
-
- /*
- * A network interface was specified, so let's bind to it.
- */
- if (netif != NULL) {
- if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) {
- NET_ThrowNew(env, errno, "Can't bind socket");
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
- }
- SET_NONBLOCKING(fd);
-
- /* no need to use NET_Connect as non-blocking */
- him6.sin6_port = htons((short) 7); /* Echo port */
- connect_rv = JVM_Connect(fd, (struct sockaddr *)&him6, len);
-
- /**
- * connection established or refused immediately, either way it means
- * we were able to reach the host!
- */
- if (connect_rv == 0 || errno == ECONNREFUSED) {
- untagSocket(env, fd);
- close(fd);
- return JNI_TRUE;
- } else {
- int optlen;
-
- switch (errno) {
- case ENETUNREACH: /* Network Unreachable */
- case EAFNOSUPPORT: /* Address Family not supported */
- case EADDRNOTAVAIL: /* address is not available on the remote machine */
-#ifdef __linux__
- case EINVAL:
- case EHOSTUNREACH:
- /*
- * On some Linuxes, when bound to the loopback interface, connect
- * loopback interface, connect will fail and errno will
- * be set to EINVAL or EHOSTUNREACH. When that happens,
- * don't throw an exception, just return false.
- */
-#endif /* __linux__ */
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
-
- if (errno != EINPROGRESS) {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
- "connect failed");
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
-
- timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout);
-
- if (timeout >= 0) {
- /* has connection been established */
- optlen = sizeof(connect_rv);
- if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
- &optlen) <0) {
- connect_rv = errno;
- }
- if (connect_rv == 0 || ECONNREFUSED) {
- untagSocket(env, fd);
- close(fd);
- return JNI_TRUE;
- }
- }
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
-#else /* AF_INET6 */
- return JNI_FALSE;
-#endif /* AF_INET6 */
-}
-
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(Inet6AddressImpl, isReachable0, "([BII[BII)Z"),
NATIVE_METHOD(Inet6AddressImpl, getHostByAddr0, "([B)Ljava/lang/String;"),
};
diff --git a/ojluni/src/main/native/Register.cpp b/ojluni/src/main/native/Register.cpp
index 0d31d02..9d40c16 100644
--- a/ojluni/src/main/native/Register.cpp
+++ b/ojluni/src/main/native/Register.cpp
@@ -25,12 +25,13 @@
#define LOG_TAG "libcore" // We'll be next to "dalvikvm" in the log; make the distinction clear.
-#include "cutils/log.h"
+#include <stdlib.h>
+
+#include <android/log.h>
+
#include "JniConstants.h"
#include "ScopedLocalFrame.h"
-#include <stdlib.h>
-
extern "C" {
extern void register_java_io_Console(JNIEnv* env);
diff --git a/ojluni/src/main/native/System.c b/ojluni/src/main/native/System.c
index 4c547c0..3386e47 100644
--- a/ojluni/src/main/native/System.c
+++ b/ojluni/src/main/native/System.c
@@ -22,19 +22,20 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-#include <string.h>
-#include <stdlib.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <android/log.h>
+
+#include "io_util.h"
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
-#include "io_util.h"
-
#include "openssl/opensslv.h"
#include "zlib.h"
#include "JNIHelp.h"
-#include "cutils/log.h"
#if defined(__ANDROID__)
void android_get_LD_LIBRARY_PATH(char*, size_t);
#endif
diff --git a/ojluni/src/main/native/java_net_Inet4AddressImpl.h b/ojluni/src/main/native/java_net_Inet4AddressImpl.h
deleted file mode 100644
index 8ee8820..0000000
--- a/ojluni/src/main/native/java_net_Inet4AddressImpl.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* This file was generated from java/net/Inet4AddressImpl.java and
- * is licensed under the same terms. The copyright and license information
- * for java/net/Inet4AddressImpl.java follows.
- *
- * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class java_net_Inet4AddressImpl */
-
-#ifndef _Included_java_net_Inet4AddressImpl
-#define _Included_java_net_Inet4AddressImpl
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: java_net_Inet4AddressImpl
- * Method: getLocalHostName
- * Signature: ()Ljava/lang/String;
- */
-JNIEXPORT jstring JNICALL Inet4AddressImpl_getLocalHostName
- (JNIEnv *, jobject);
-
-/*
- * Class: java_net_Inet4AddressImpl
- * Method: lookupAllHostAddr
- * Signature: (Ljava/lang/String;)[Ljava/net/InetAddress;
- */
-JNIEXPORT jobjectArray JNICALL Inet4AddressImpl_lookupAllHostAddr
- (JNIEnv *, jobject, jstring);
-
-/*
- * Class: java_net_Inet4AddressImpl
- * Method: getHostByAddr
- * Signature: ([B)Ljava/lang/String;
- */
-JNIEXPORT jstring JNICALL Inet4AddressImpl_getHostByAddr
- (JNIEnv *, jobject, jbyteArray);
-
-/*
- * Class: java_net_Inet4AddressImpl
- * Method: isReachable0
- * Signature: ([BI[BI)Z
- */
-JNIEXPORT jboolean JNICALL Inet4AddressImpl_isReachable0
- (JNIEnv *, jobject, jbyteArray, jint, jbyteArray, jint);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/ojluni/src/main/native/openjdksub.mk b/ojluni/src/main/native/openjdksub.mk
index 3a3fcb0..ff82754 100644
--- a/ojluni/src/main/native/openjdksub.mk
+++ b/ojluni/src/main/native/openjdksub.mk
@@ -54,7 +54,6 @@
PlainSocketImpl.c \
PlainDatagramSocketImpl.c \
DatagramPacket.c \
- Inet4AddressImpl.c \
Inet6AddressImpl.c \
ServerSocketChannelImpl.c \
SocketInputStream.c \
diff --git a/openjdk_java_files.mk b/openjdk_java_files.mk
index 6a1c3e6..8bf5681 100644
--- a/openjdk_java_files.mk
+++ b/openjdk_java_files.mk
@@ -1421,7 +1421,6 @@
ojluni/src/main/java/sun/security/action/GetIntegerAction.java \
ojluni/src/main/java/sun/security/action/GetPropertyAction.java \
ojluni/src/main/java/sun/security/action/LoadLibraryAction.java \
- ojluni/src/main/java/sun/security/action/PutAllAction.java \
ojluni/src/main/java/sun/security/jca/GetInstance.java \
ojluni/src/main/java/sun/security/jca/JCAUtil.java \
ojluni/src/main/java/sun/security/jca/ProviderConfig.java \
diff --git a/test-rules/src/main/java/libcore/junit/junit3/TestCaseWithRules.java b/test-rules/src/main/java/libcore/junit/junit3/TestCaseWithRules.java
new file mode 100644
index 0000000..b5acc82
--- /dev/null
+++ b/test-rules/src/main/java/libcore/junit/junit3/TestCaseWithRules.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2016 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 libcore.junit.junit3;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import junit.framework.TestCase;
+import org.junit.Rule;
+import org.junit.rules.MethodRule;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.MultipleFailureException;
+import org.junit.runners.model.Statement;
+import org.junit.runners.model.TestClass;
+
+import static org.junit.internal.runners.rules.RuleFieldValidator.RULE_VALIDATOR;
+
+/**
+ * A {@link TestCase} that supports the @Rule annotation from JUnit 4.
+ *
+ * <p>It supports both {@link TestRule} and {@link MethodRule} based rules when used with the
+ * {@code @Rule} annotation on public fields. The rules encapsulate the {@link TestCase#runBare()}
+ * method and so are run before the {@link TestCase#setUp()} and after the
+ * {@link TestCase#tearDown()} methods.
+ *
+ * <p>Classes that extend this must have a single no argument constructor.
+ */
+public abstract class TestCaseWithRules extends TestCase {
+
+ private final TestClass testClass;
+
+ private final List<Throwable> validationErrors;
+
+ public TestCaseWithRules() {
+ testClass = new TestClass(getClass());
+
+ validationErrors = new ArrayList<>();
+ RULE_VALIDATOR.validate(testClass, validationErrors);
+ }
+
+ @Override
+ public void runBare() throws Throwable {
+ if (!validationErrors.isEmpty()) {
+ throw new MultipleFailureException(validationErrors);
+ }
+
+ Statement statement = new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ superRunBare();
+ }
+ };
+
+ final String name = getName();
+ FrameworkMethod frameworkMethod;
+ try {
+ Method method = getClass().getMethod(name, (Class[]) null);
+ frameworkMethod = new FrameworkMethod(method);
+ } catch (NoSuchMethodException e) {
+ frameworkMethod = new FrameworkMethod(null) {
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public Annotation[] getAnnotations() {
+ return new Annotation[0];
+ }
+
+ @Override
+ public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
+ return null;
+ }
+ };
+ }
+ Description description =
+ Description.createTestDescription(getClass(), frameworkMethod.getName(),
+ frameworkMethod.getAnnotations());
+
+ List<Object> rules = testClass.getAnnotatedFieldValues(this, Rule.class, Object.class);
+ for (Object rule : rules) {
+ if (rule instanceof TestRule) {
+ statement = ((TestRule) rule).apply(statement, description);
+ } else {
+ statement = ((MethodRule) rule).apply(statement, frameworkMethod, this);
+ }
+ }
+
+ statement.evaluate();
+ }
+
+ private void superRunBare() throws Throwable {
+ super.runBare();
+ }
+}
diff --git a/test-rules/src/main/java/libcore/junit/util/ResourceLeakageDetector.java b/test-rules/src/main/java/libcore/junit/util/ResourceLeakageDetector.java
new file mode 100644
index 0000000..dae7978
--- /dev/null
+++ b/test-rules/src/main/java/libcore/junit/util/ResourceLeakageDetector.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2016 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 libcore.junit.util;
+
+import java.lang.reflect.Method;
+import java.util.function.BiConsumer;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * Provides support for testing classes that own resources which must not leak.
+ *
+ * <p><strong>This will not detect any resource leakages in OpenJDK</strong></p>
+ */
+public class ResourceLeakageDetector {
+ private static final LeakageDetectorRule LEAKAGE_DETECTOR_RULE;
+ private static final BiConsumer<Object, Integer> FINALIZER_CHECKER;
+
+ static {
+ LeakageDetectorRule leakageDetectorRule;
+ BiConsumer<Object, Integer> finalizerChecker;
+ try {
+ // Make sure that the CloseGuard class exists; this ensures that this is not
+ // running on a RI JVM.
+ Class.forName("dalvik.system.CloseGuard");
+
+ // Access the underlying support class using reflection in order to prevent any compile
+ // time dependencies on it so as to allow this to compile on OpenJDK.
+ Class<?> closeGuardSupportClass = Class.forName("dalvik.system.CloseGuardSupport");
+ Method method = closeGuardSupportClass.getMethod("getRule");
+ leakageDetectorRule = new LeakageDetectorRule((TestRule) method.invoke(null));
+
+ finalizerChecker = getFinalizerChecker(closeGuardSupportClass);
+
+ } catch (ReflectiveOperationException e) {
+ System.err.println("Resource leakage will not be detected; "
+ + "this is expected in the reference implementation");
+ e.printStackTrace(System.err);
+
+ // Could not access the class for some reason so have a rule that does nothing and a
+ // finalizer checker that checks nothing. This should ensure that tests work properly
+ // on OpenJDK even though it does not support CloseGuard.
+ leakageDetectorRule = new LeakageDetectorRule(RuleChain.emptyRuleChain());
+ finalizerChecker = new BiConsumer<Object, Integer>() {
+ @Override
+ public void accept(Object o, Integer integer) {
+ // Do nothing.
+ }
+ };
+ }
+
+ LEAKAGE_DETECTOR_RULE = leakageDetectorRule;
+ FINALIZER_CHECKER = finalizerChecker;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static BiConsumer<Object, Integer> getFinalizerChecker(Class<?> closeGuardSupportClass)
+ throws ReflectiveOperationException {
+ Method method = closeGuardSupportClass.getMethod("getFinalizerChecker");
+ return (BiConsumer<Object, Integer>) method.invoke(null);
+ }
+
+ /**
+ * @return the {@link LeakageDetectorRule}
+ */
+ public static LeakageDetectorRule getRule() {
+ return LEAKAGE_DETECTOR_RULE;
+ }
+
+ /**
+ * A {@link TestRule} that will fail a test if it detects any resources that were allocated
+ * during the test but were not released.
+ *
+ * <p>This only tracks resources that were allocated on the test thread, although it does not
+ * care what thread they were released on. This avoids flaky false positives where a background
+ * thread allocates a resource during a test but releases it after the test.
+ *
+ * <p>It is still possible to have a false positive in the case where the test causes a caching
+ * mechanism to open a resource and hold it open past the end of the test. In that case if there
+ * is no way to clear the cached data then it should be relatively simple to move the code that
+ * invokes the caching mechanism to outside the scope of this rule. i.e.
+ *
+ * <pre>{@code
+ * @Rule
+ * public final TestRule ruleChain = org.junit.rules.RuleChain
+ * .outerRule(new ...invoke caching mechanism...)
+ * .around(CloseGuardSupport.getRule());
+ * }</pre>
+ *
+ * @return a {@link TestRule} that detects resource leakages, or one that does nothing if
+ * resource leakage detection is not supported.
+ */
+ public static class LeakageDetectorRule implements TestRule {
+
+ private final TestRule leakageDetectorRule;
+
+ private LeakageDetectorRule(TestRule leakageDetectorRule) {
+ this.leakageDetectorRule = leakageDetectorRule;
+ }
+
+ @Override
+ public Statement apply(Statement base, Description description) {
+ return leakageDetectorRule.apply(base, description);
+ }
+
+ /**
+ * Ensure that when the supplied object is finalized that it detects the expected number of
+ * unreleased resources.
+ *
+ * <p>This helps ensure that classes which own resources protected using {@code CloseGuard}
+ * support leakage detection.
+ *
+ * <p>This must only be called from within the test currently being run otherwise it will
+ * fail if the resource leakage detected mechanism is disabled, e.g. in CTS.
+ *
+ * <p>Use as follows:
+ * <pre>
+ * Object object = ...create and 'open' an object encapsulating a protected resource...;
+ * // Check to make sure that the object reports a resource leak when it is finalized.
+ * assertUnreleasedResourceCount(object, 1);
+ *
+ * object = ... create, 'open' and then 'close' another object ...;
+ * // Check to make sure that the object does not have any unreleased resources.
+ * assertUnreleasedResourceCount(object, 0);
+ * </pre>
+ *
+ * @param owner the object that owns the resource and uses {@code CloseGuard} object to detect
+ * when the resource is not released.
+ * @param expectedCount the expected number of unreleased resources.
+ */
+ public void assertUnreleasedResourceCount(Object owner, int expectedCount) {
+ FINALIZER_CHECKER.accept(owner, expectedCount);
+ }
+ }
+}