Merge "Remove unused method."
diff --git a/NativeCode.mk b/NativeCode.mk
index 67d127a..0ef43a7 100644
--- a/NativeCode.mk
+++ b/NativeCode.mk
@@ -138,6 +138,28 @@
LOCAL_CXX_STL := libc++
include $(BUILD_SHARED_LIBRARY)
+# Debug version of libopenjdk. Depends on libopenjdkjvmd.
+include $(CLEAR_VARS)
+
+LOCAL_CFLAGS += $(libart_cflags)
+LOCAL_CPPFLAGS += $(core_cppflags)
+ifeq ($(TARGET_ARCH),arm)
+# Ignore "note: the mangling of 'va_list' has changed in GCC 4.4"
+LOCAL_CFLAGS += -Wno-psabi
+endif
+
+LOCAL_CFLAGS += $(openjdk_cflags)
+LOCAL_SRC_FILES := $(openjdk_core_src_files)
+LOCAL_C_INCLUDES := $(core_c_includes)
+LOCAL_SHARED_LIBRARIES := $(core_shared_libraries) libcrypto libicuuc libssl libz
+LOCAL_SHARED_LIBRARIES += libopenjdkjvmd libnativehelper libdl
+LOCAL_STATIC_LIBRARIES := $(core_static_libraries) libfdlibm
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libopenjdkd
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/ojluni/NOTICE
+LOCAL_CXX_STL := libc++
+include $(BUILD_SHARED_LIBRARY)
+
# Test JNI library.
ifeq ($(LIBCORE_SKIP_TESTS),)
@@ -214,6 +236,22 @@
LOCAL_CXX_STL := libc++
include $(BUILD_HOST_SHARED_LIBRARY)
+# Debug version of libopenjdk (host). Depends on libopenjdkjvmd.
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(openjdk_core_src_files)
+LOCAL_C_INCLUDES := $(core_c_includes)
+LOCAL_CFLAGS := -D_LARGEFILE64_SOURCE -D_GNU_SOURCE -DLINUX -D__GLIBC__ # Sigh.
+LOCAL_CFLAGS += $(openjdk_cflags)
+LOCAL_SHARED_LIBRARIES := $(core_shared_libraries) libicuuc-host libcrypto-host libz-host
+LOCAL_SHARED_LIBRARIES += libopenjdkjvmd libnativehelper
+LOCAL_STATIC_LIBRARIES := $(core_static_libraries) libfdlibm
+LOCAL_MODULE_TAGS := optional
+LOCAL_LDLIBS += -ldl -lpthread
+LOCAL_MODULE := libopenjdkd
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/ojluni/NOTICE
+LOCAL_MULTILIB := both
+include $(BUILD_HOST_SHARED_LIBRARY)
+
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(openjdk_core_src_files)
LOCAL_C_INCLUDES := $(core_c_includes)
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/TimerTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/TimerTest.java
index a353007..33b17c4 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/TimerTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/TimerTest.java
@@ -1111,17 +1111,20 @@
private static class IncrementCounterTaskAndPossiblyThrowAfter extends TimerTask {
private final AtomicLong counter;
-
+ private final int incrementAmount;
private final boolean willThrow;
- IncrementCounterTaskAndPossiblyThrowAfter(AtomicLong counter, boolean willThrow) {
+
+ IncrementCounterTaskAndPossiblyThrowAfter(
+ AtomicLong counter, int incrementAmount, boolean willThrow) {
this.counter = counter;
+ this.incrementAmount = incrementAmount;
this.willThrow = willThrow;
}
@Override
public void run() {
- counter.incrementAndGet();
+ counter.addAndGet(incrementAmount);
if (willThrow) {
throw new IllegalStateException("TimerTask runtime exception from run()");
}
@@ -1153,23 +1156,35 @@
try {
Timer t = new Timer();
final AtomicLong counter = new AtomicLong();
- TimerTask task1 = new IncrementCounterTaskAndPossiblyThrowAfter(
+
+ // Schedule tasks to run:
+ // A) {In 1 millis} Increment a counter by 1 and throw an exception
+ // B) {In 100 millis} Increment a counter by 1000 (but it's not intended to be executed
+ // because of the previous exception).
+ // We want A and B to be scheduled before A runs.
+ // We add them in reverse order.
+ // We have ~99 millis after scheduling B to schedule A. If A ran before we scheduled B
+ // we would get an exception when we came to schedule B.
+ TimerTask taskThatDoesntThrow = new IncrementCounterTaskAndPossiblyThrowAfter(
counter,
- true /* willThrow */);
- TimerTask task2 = new IncrementCounterTaskAndPossiblyThrowAfter(
- counter,
+ 1000, /* incrementAmount */
false /* willThrow */);
- t.scheduleAtFixedRate(task1, 1 /* delay */, 100 /* period */);
- t.schedule(task2, 100 /* delay */);
+ TimerTask taskThatThrows = new IncrementCounterTaskAndPossiblyThrowAfter(
+ counter,
+ 1, /* incrementAmount */
+ true /* willThrow */);
+ t.schedule(taskThatDoesntThrow, 100 /* delay */);
+ t.scheduleAtFixedRate(taskThatThrows, 1 /* delay */, 100 /* period */);
+
swallowUncaughtExceptionHandler.waitForException(1000);
// Check the counter wasn't increased more than once (ie, the exception killed the
// execution thread).
assertEquals("Counter should be 1, and is: " + counter.get(), 1, counter.get());
- assertTrue("The timer should not cancel the tasks", task1.cancel());
- assertTrue("The timer should not cancel the tasks", task2.cancel());
+ assertTrue("The timer should not cancel the tasks", taskThatDoesntThrow.cancel());
+ assertTrue("The timer should not cancel the tasks", taskThatThrows.cancel());
- TimerTask task3 = new TimerTask() {
+ TimerTask otherTask = new TimerTask() {
@Override
public void run() {
counter.incrementAndGet();
@@ -1177,7 +1192,7 @@
};
try {
- t.schedule(task3, 1);
+ t.schedule(otherTask, 1);
fail("Timer should be cancelled and no new tasks should be allowed");
} catch (Exception expected) {
// Expected.
@@ -1198,23 +1213,35 @@
try {
Timer t = new Timer();
final AtomicLong counter = new AtomicLong();
- TimerTask task1 = new IncrementCounterTaskAndPossiblyThrowAfter(
+
+ // Schedule tasks to run:
+ // A) {In 1 millis} Increment a counter by 1 and throw an exception
+ // B) {In 100 millis} Increment a counter by 1000 (but it's not intended to be executed
+ // because of the previous exception).
+ // We want A and B to be scheduled before A runs.
+ // We add them in reverse order.
+ // We have ~99 millis after scheduling B to schedule A. If A ran before we scheduled B
+ // we would get an exception when we came to schedule B.
+
+ TimerTask taskThatDoesntThrow = new IncrementCounterTaskAndPossiblyThrowAfter(
counter,
- true /* willThrow */);
- TimerTask task2 = new IncrementCounterTaskAndPossiblyThrowAfter(
- counter,
+ 1000, /* incrementAmount */
false /* willThrow */);
- t.scheduleAtFixedRate(task1, 1 /* delay */, 100 /* period */);
- t.schedule(task2, 100 /* delay */);
+ TimerTask taskThatThrows = new IncrementCounterTaskAndPossiblyThrowAfter(
+ counter,
+ 1, /* incrementAmount */
+ true /* willThrow */);
+ t.schedule(taskThatDoesntThrow, 100 /* delay */);
+ t.scheduleAtFixedRate(taskThatThrows, 1 /* delay */, 100 /* period */);
swallowUncaughtExceptionHandler.waitForException(1000);
// Check the counter wasn't increased more than once (ie, the exception killed the
// execution thread).
assertEquals("Counter should be 1, and is: " + counter.get(), 1, counter.get());
t.purge();
- assertTrue("The timer should not cancel the tasks", task1.cancel());
- assertTrue("The timer should not cancel the tasks", task2.cancel());
+ assertTrue("The timer should not cancel the tasks", taskThatDoesntThrow.cancel());
+ assertTrue("The timer should not cancel the tasks", taskThatThrows.cancel());
- TimerTask task3 = new TimerTask() {
+ TimerTask otherTask = new TimerTask() {
@Override
public void run() {
counter.incrementAndGet();
@@ -1222,7 +1249,7 @@
};
try {
- t.schedule(task3, 1);
+ t.schedule(otherTask, 1);
fail("Timer should be cancelled and no new tasks should be allowed");
} catch (Exception expected) {
// Expected.
diff --git a/harmony-tests/src/test/resources/serialization/org/apache/harmony/tests/java/util/Locale_Bug_26387905.ser b/harmony-tests/src/test/resources/serialization/org/apache/harmony/tests/java/util/Locale_Bug_26387905.ser
new file mode 100644
index 0000000..e467a39
--- /dev/null
+++ b/harmony-tests/src/test/resources/serialization/org/apache/harmony/tests/java/util/Locale_Bug_26387905.ser
Binary files differ
diff --git a/luni/src/test/java/dalvik/system/BlockGuardTest.java b/luni/src/test/java/dalvik/system/BlockGuardTest.java
new file mode 100644
index 0000000..24313cd
--- /dev/null
+++ b/luni/src/test/java/dalvik/system/BlockGuardTest.java
@@ -0,0 +1,198 @@
+/*
+ * 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 junit.framework.TestCase;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by narayan on 1/7/16.
+ */
+public class BlockGuardTest extends TestCase {
+
+ private BlockGuard.Policy oldPolicy;
+ private RecordingPolicy recorder = new RecordingPolicy();
+
+ @Override
+ public void setUp() {
+ oldPolicy = BlockGuard.getThreadPolicy();
+ BlockGuard.setThreadPolicy(recorder);
+ }
+
+ @Override
+ public void tearDown() {
+ BlockGuard.setThreadPolicy(oldPolicy);
+ recorder.clear();
+ }
+
+ public void testFile() throws Exception {
+ File f = File.createTempFile("foo", "bar");
+ recorder.expectAndClear("onReadFromDisk", "onWriteToDisk");
+
+ f.getAbsolutePath();
+ f.getParentFile();
+ f.getName();
+ f.getParent();
+ f.getPath();
+ f.isAbsolute();
+ recorder.expectNoViolations();
+
+ f.mkdir();
+ recorder.expectAndClear("onWriteToDisk");
+
+ f.listFiles();
+ recorder.expectAndClear("onReadFromDisk");
+
+ f.list();
+ recorder.expectAndClear("onReadFromDisk");
+
+ f.length();
+ recorder.expectAndClear("onReadFromDisk");
+
+ f.lastModified();
+ recorder.expectAndClear("onReadFromDisk");
+
+ f.canExecute();
+ recorder.expectAndClear("onReadFromDisk");
+
+ f.canRead();
+ recorder.expectAndClear("onReadFromDisk");
+
+ f.canWrite();
+ recorder.expectAndClear("onReadFromDisk");
+
+ f.isFile();
+ recorder.expectAndClear("onReadFromDisk");
+
+ f.isDirectory();
+ recorder.expectAndClear("onReadFromDisk");
+
+ f.setExecutable(true, false);
+ recorder.expectAndClear("onWriteToDisk");
+
+ f.setReadable(true, false);
+ recorder.expectAndClear("onWriteToDisk");
+
+ f.setWritable(true, false);
+ recorder.expectAndClear("onWriteToDisk");
+
+ f.delete();
+ recorder.expectAndClear("onWriteToDisk");
+ }
+
+ public void testFileInputStream() throws Exception {
+ File f = new File("/proc/version");
+ recorder.clear();
+
+ FileInputStream fis = new FileInputStream(f);
+ recorder.expectAndClear("onReadFromDisk");
+
+ fis.read(new byte[4],0, 4);
+ recorder.expectAndClear("onReadFromDisk");
+
+ fis.read();
+ recorder.expectAndClear("onReadFromDisk");
+
+ fis.skip(1);
+ recorder.expectAndClear("onReadFromDisk");
+
+ fis.close();
+ }
+
+ public void testFileOutputStream() throws Exception {
+ File f = File.createTempFile("foo", "bar");
+ recorder.clear();
+
+ FileOutputStream fos = new FileOutputStream(f);
+ recorder.expectAndClear("onWriteToDisk");
+
+ fos.write(new byte[3]);
+ recorder.expectAndClear("onWriteToDisk");
+
+ fos.write(4);
+ recorder.expectAndClear("onWriteToDisk");
+
+ fos.flush();
+ recorder.expectNoViolations();
+
+ fos.close();
+ recorder.expectNoViolations();
+ }
+
+
+ public static class RecordingPolicy implements BlockGuard.Policy {
+ private final List<String> violations = new ArrayList<>();
+
+ @Override
+ public void onWriteToDisk() {
+ addViolation("onWriteToDisk");
+ }
+
+ @Override
+ public void onReadFromDisk() {
+ addViolation("onReadFromDisk");
+ }
+
+ @Override
+ public void onNetwork() {
+ addViolation("onNetwork");
+ }
+
+ private void addViolation(String type) {
+ StackTraceElement[] threadTrace = Thread.currentThread().getStackTrace();
+
+ final StackTraceElement violator = threadTrace[4];
+ violations.add(type + " [caller= " + violator.getMethodName() + "]");
+ }
+
+ public void clear() {
+ violations.clear();
+ }
+
+ public void expectNoViolations() {
+ if (violations.size() != 0) {
+ throw new AssertionError("Expected 0 violations but found " + violations.size());
+ }
+ }
+
+ public void expectAndClear(String... expected) {
+ if (expected.length != violations.size()) {
+ throw new AssertionError("Expected " + expected.length + " violations but found "
+ + violations.size());
+ }
+
+ for (int i = 0; i < expected.length; ++i) {
+ if (!violations.get(i).startsWith(expected[i])) {
+ throw new AssertionError("Expected: " + expected[i] + " but was "
+ + violations.get(i));
+ }
+ }
+
+ clear();
+ }
+
+ @Override
+ public int getPolicyMask() {
+ return 0;
+ }
+ }
+}
diff --git a/luni/src/test/java/libcore/io/ClassPathURLStreamHandlerTest.java b/luni/src/test/java/libcore/io/ClassPathURLStreamHandlerTest.java
index 12ceb4f..151c3f4 100644
--- a/luni/src/test/java/libcore/io/ClassPathURLStreamHandlerTest.java
+++ b/luni/src/test/java/libcore/io/ClassPathURLStreamHandlerTest.java
@@ -43,6 +43,7 @@
private static final String ENTRY_WITH_SPACES_ENCODED = "file%20with%20spaces.txt";
private static final String ENTRY_WITH_SPACES_UNENCODED = "file with spaces.txt";
private static final String ENTRY_THAT_NEEDS_ESCAPING = "file_with_percent20_%20.txt";
+ private static final String ENTRY_THAT_NEEDS_ESCAPING_ENCODED = "file_with_percent20_%2520.txt";
private static final String ENTRY_WITH_RELATIVE_PATH = "foo/../foo/bar/baz.txt";
private static final String MISSING_ENTRY = "Wrong.resource";
@@ -71,20 +72,18 @@
String fileName = jarFile.getPath();
ClassPathURLStreamHandler streamHandler = new ClassPathURLStreamHandler(fileName);
- assertNotNull(streamHandler.getEntryUrlOrNull(ENTRY_IN_ROOT));
- assertNotNull(streamHandler.getEntryUrlOrNull(ENTRY_IN_SUBDIR));
- assertNotNull(streamHandler.getEntryUrlOrNull(ENTRY_WITH_SPACES_UNENCODED));
- assertNotNull(streamHandler.getEntryUrlOrNull(ENTRY_THAT_NEEDS_ESCAPING));
+ checkGetEntryUrlOrNull(streamHandler, ENTRY_IN_ROOT, ENTRY_IN_ROOT);
+ checkGetEntryUrlOrNull(streamHandler, ENTRY_IN_SUBDIR, ENTRY_IN_SUBDIR);
+ checkGetEntryUrlOrNull(streamHandler, ENTRY_WITH_SPACES_UNENCODED,
+ ENTRY_WITH_SPACES_ENCODED);
+ checkGetEntryUrlOrNull(streamHandler, ENTRY_THAT_NEEDS_ESCAPING,
+ ENTRY_THAT_NEEDS_ESCAPING_ENCODED);
// getEntryOrNull() performs a lookup with and without trailing slash to handle directories.
// http://b/22527772
- URL urlWithoutSlash = streamHandler.getEntryUrlOrNull(DIR_ENTRY_WITHOUT_SLASH);
- assertNotNull(urlWithoutSlash);
- assertTrue(urlWithoutSlash.toString().endsWith(DIR_ENTRY_WITHOUT_SLASH));
-
- URL urlWithSlash = streamHandler.getEntryUrlOrNull(DIR_ENTRY_WITH_SLASH);
- assertNotNull(urlWithSlash);
- assertTrue(urlWithSlash.toString().endsWith(DIR_ENTRY_WITH_SLASH));
+ checkGetEntryUrlOrNull(streamHandler, DIR_ENTRY_WITHOUT_SLASH,
+ DIR_ENTRY_WITHOUT_SLASH);
+ checkGetEntryUrlOrNull(streamHandler, DIR_ENTRY_WITH_SLASH, DIR_ENTRY_WITH_SLASH);
assertNull(streamHandler.getEntryUrlOrNull(MISSING_ENTRY));
assertNull(streamHandler.getEntryUrlOrNull("/" + ENTRY_IN_ROOT));
@@ -96,6 +95,24 @@
streamHandler.close();
}
+ /**
+ * Check that the call to {@link ClassPathURLStreamHandler#getEntryUrlOrNull(String)} works as
+ * expected.
+ */
+ private void checkGetEntryUrlOrNull(ClassPathURLStreamHandler streamHandler,
+ String entryName, String expectedJarRelativeURI) throws IOException {
+
+ String fileName = jarFile.getPath();
+ URL urlOrNull = streamHandler.getEntryUrlOrNull(entryName);
+ assertNotNull("URL was unexpectedly null for " + entryName, urlOrNull);
+ assertEquals("jar:file:" + fileName + "!/" + expectedJarRelativeURI,
+ urlOrNull.toExternalForm());
+
+ // Make sure that the resource could be opened and the correct contents returned, i.e. the
+ // same as those read from the jar file directly.
+ assertOpenConnectionOk(jarFile, expectedJarRelativeURI, streamHandler);
+ }
+
public void testIsEntryStored() throws IOException {
String fileName = jarFile.getPath();
ClassPathURLStreamHandler streamHandler = new ClassPathURLStreamHandler(fileName);
diff --git a/luni/src/test/java/libcore/java/net/URITest.java b/luni/src/test/java/libcore/java/net/URITest.java
index 9fcae92..e4c07a2 100644
--- a/luni/src/test/java/libcore/java/net/URITest.java
+++ b/luni/src/test/java/libcore/java/net/URITest.java
@@ -713,9 +713,13 @@
assertEquals("a_b.c.d.net", uri.getHost());
}
+ // RFC1034#section-3.5 doesn't permit empty labels in hostnames, but we
+ // accepted this prior to N and the behavior is used by some apps. We need
+ // to keep the behavior for now for compatibility.
// http://b/25991669
- public void testHostWithLeadingPeriod() throws Exception {
- assertEquals(".vk.com", new URI("https://.vk.com/").getHost());
+ public void testHostWithEmptyLabel() throws Exception {
+ assertEquals(".example.com", new URI("http://.example.com/").getHost());
+ assertEquals("example..com", new URI("http://example..com/").getHost());
}
// Adding a new test? Consider adding an equivalent test to URLTest.java
diff --git a/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java b/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java
index a54b30a..c901a08 100644
--- a/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java
@@ -32,24 +32,10 @@
import java.nio.channels.UnresolvedAddressException;
import java.util.Set;
-import tests.io.MockOs;
-
import static android.system.OsConstants.*;
public class SocketChannelTest extends junit.framework.TestCase {
- private final MockOs mockOs = new MockOs();
-
- @Override
- public void setUp() throws Exception {
- mockOs.install();
- }
-
- @Override
- protected void tearDown() throws Exception {
- mockOs.uninstall();
- }
-
public void test_read_intoReadOnlyByteArrays() throws Exception {
ByteBuffer readOnly = ByteBuffer.allocate(1).asReadOnlyBuffer();
ServerSocket ss = new ServerSocket(0);
@@ -74,8 +60,6 @@
// https://code.google.com/p/android/issues/detail?id=56684
public void test_56684() throws Exception {
- mockOs.enqueueFault("connect", ENETUNREACH);
-
SocketChannel sc = SocketChannel.open();
sc.configureBlocking(false);
@@ -83,7 +67,13 @@
SelectionKey selectionKey = sc.register(selector, SelectionKey.OP_CONNECT);
try {
- sc.connect(new InetSocketAddress(InetAddress.getByAddress(new byte[] { 0, 0, 0, 0 }), 0));
+ // This test originally mocked the connect syscall to return ENETUNREACH.
+ // This is not easily doable in openJdk libcore, but a connect to broadcast
+ // address (255.255.255.255) for a TCP connection produces ENETUNREACH
+ // Kernel code that does it is at
+ // http://lxr.free-electrons.com/source/net/ipv4/tcp_ipv4.c?v=3.18#L182
+ sc.connect(new InetSocketAddress(InetAddress.getByAddress(new byte[] {
+ (byte) 255, (byte) 255, (byte)255, (byte)255 }), 0));
fail();
} catch (ConnectException ex) {
}
diff --git a/luni/src/test/java/libcore/java/nio/charset/CharsetTest.java b/luni/src/test/java/libcore/java/nio/charset/CharsetTest.java
new file mode 100644
index 0000000..a330e0d
--- /dev/null
+++ b/luni/src/test/java/libcore/java/nio/charset/CharsetTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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.nio.charset;
+
+import java.nio.charset.Charset;
+
+public class CharsetTest extends junit.framework.TestCase {
+
+ public void test_nonstandardCharsetName() {
+ Charset cs = Charset.forName("UTF8");
+ assertNotNull(cs);
+ assertEquals("UTF-8", cs.name());
+
+ // Make sure that caching correctly handles nonstandard name.
+ // http://b/26457745
+ assertNotNull(Charset.forName("UTF8"));
+ }
+
+}
diff --git a/luni/src/test/java/libcore/java/util/LocaleTest.java b/luni/src/test/java/libcore/java/util/LocaleTest.java
index 45b31b9..8d184e2 100644
--- a/luni/src/test/java/libcore/java/util/LocaleTest.java
+++ b/luni/src/test/java/libcore/java/util/LocaleTest.java
@@ -16,6 +16,7 @@
package libcore.java.util;
+import java.io.ObjectInputStream;
import java.text.BreakIterator;
import java.text.Collator;
import java.text.DateFormat;
@@ -1240,4 +1241,13 @@
b.setExtension('u', "nu-thai");
assertEquals("ar-EG-u-nu-thai", b.build().toLanguageTag());
}
+
+ // http://b/26387905
+ public void test_SerializationBug_26387905() throws Exception {
+ try (ObjectInputStream oinput = new ObjectInputStream(getClass()
+ .getResource("/serialization/org/apache/harmony/tests/java/util/Locale_Bug_26387905.ser")
+ .openStream())) {
+ Locale l = (Locale) oinput.readObject();
+ }
+ }
}
diff --git a/ojluni/src/main/java/java/io/File.java b/ojluni/src/main/java/java/io/File.java
index ee51a05..4d1f9d1 100755
--- a/ojluni/src/main/java/java/io/File.java
+++ b/ojluni/src/main/java/java/io/File.java
@@ -153,7 +153,7 @@
/**
* The FileSystem object representing the platform's local file system.
*/
- static private FileSystem fs = FileSystem.getFileSystem();
+ static private final FileSystem fs = FileSystem.getFileSystem();
/**
* This abstract pathname's normalized pathname string. A normalized
diff --git a/ojluni/src/main/java/java/io/FileDescriptor.java b/ojluni/src/main/java/java/io/FileDescriptor.java
index 8da266b..fa8593d 100755
--- a/ojluni/src/main/java/java/io/FileDescriptor.java
+++ b/ojluni/src/main/java/java/io/FileDescriptor.java
@@ -51,24 +51,15 @@
private int descriptor;
/**
- * A counter for tracking the FIS/FOS/RAF instances that
- * use this FileDescriptor. The FIS/FOS.finalize() will not release
- * the FileDescriptor if it is still under user by a stream.
- */
- private AtomicInteger useCount;
-
- /**
* Constructs an (invalid) FileDescriptor
* object.
*/
- public /**/ FileDescriptor() {
+ public FileDescriptor() {
descriptor = -1;
- useCount = new AtomicInteger();
}
- private /* */ FileDescriptor(int descriptor) {
+ private FileDescriptor(int descriptor) {
this.descriptor = descriptor;
- useCount = new AtomicInteger();
}
/**
@@ -184,13 +175,4 @@
private static native boolean isSocket(int descriptor);
- // package private methods used by FIS, FOS and RAF
-
- int incrementAndGetUseCount() {
- return useCount.incrementAndGet();
- }
-
- int decrementAndGetUseCount() {
- return useCount.decrementAndGet();
- }
}
diff --git a/ojluni/src/main/java/java/io/FileInputStream.java b/ojluni/src/main/java/java/io/FileInputStream.java
index b6b3780..a6d9a9f 100755
--- a/ojluni/src/main/java/java/io/FileInputStream.java
+++ b/ojluni/src/main/java/java/io/FileInputStream.java
@@ -27,6 +27,9 @@
package java.io;
import java.nio.channels.FileChannel;
+
+import dalvik.system.BlockGuard;
+import dalvik.system.CloseGuard;
import sun.nio.ch.FileChannelImpl;
import sun.misc.IoTrace;
import libcore.io.IoBridge;
@@ -61,6 +64,9 @@
private final Object closeLock = new Object();
private volatile boolean closed = false;
+ private final boolean isFdOwner;
+
+ private final CloseGuard guard = CloseGuard.get();
/**
* Creates a <code>FileInputStream</code> by
@@ -133,9 +139,12 @@
throw new FileNotFoundException("Invalid file path");
}
fd = new FileDescriptor();
- fd.incrementAndGetUseCount();
+ isFdOwner = true;
this.path = name;
+
+ BlockGuard.getThreadPolicy().onReadFromDisk();
open(name);
+ guard.open("close");
}
/**
@@ -171,14 +180,8 @@
security.checkRead(fdObj);
}
fd = fdObj;
+ isFdOwner = false;
path = null;
-
- /*
- * FileDescriptor is being shared by streams.
- * Ensure that it's GC'ed only when all the streams/channels are done
- * using it.
- */
- fd.incrementAndGetUseCount();
}
/**
@@ -284,6 +287,7 @@
}
try {
+ BlockGuard.getThreadPolicy().onReadFromDisk();
return skip0(n);
} catch(UseManualSkipException e) {
return super.skip(n);
@@ -343,27 +347,19 @@
}
closed = true;
}
+
+ guard.close();
+
if (channel != null) {
/*
* Decrement the FD use count associated with the channel
* The use count is incremented whenever a new channel
* is obtained from this stream.
*/
- fd.decrementAndGetUseCount();
channel.close();
}
- /*
- * Decrement the FD use count associated with this stream
- */
- int useCount = fd.decrementAndGetUseCount();
-
- /*
- * If FileDescriptor is still in use by another stream, the finalizer
- * will not close it.
- */
- // Android change, make sure only last close closes FD.
- if ((useCount <= 0)) {
+ if (isFdOwner) {
IoBridge.closeAndSignalBlockedThreads(fd);
}
}
@@ -404,12 +400,6 @@
if (channel == null) {
channel = FileChannelImpl.open(fd, path, true, false, this);
- /*
- * Increment fd's use count. Invoking the channel's close()
- * method will result in decrementing the use count set for
- * the channel.
- */
- fd.incrementAndGetUseCount();
}
return channel;
}
@@ -429,6 +419,10 @@
* @see java.io.FileInputStream#close()
*/
protected void finalize() throws IOException {
+ if (guard != null) {
+ guard.warnIfOpen();
+ }
+
if ((fd != null) && (fd != FileDescriptor.in)) {
close();
}
diff --git a/ojluni/src/main/java/java/io/FileOutputStream.java b/ojluni/src/main/java/java/io/FileOutputStream.java
index d6cee54..10c9214 100755
--- a/ojluni/src/main/java/java/io/FileOutputStream.java
+++ b/ojluni/src/main/java/java/io/FileOutputStream.java
@@ -27,6 +27,9 @@
package java.io;
import java.nio.channels.FileChannel;
+
+import dalvik.system.BlockGuard;
+import dalvik.system.CloseGuard;
import sun.nio.ch.FileChannelImpl;
import sun.misc.IoTrace;
import libcore.io.IoBridge;
@@ -77,6 +80,9 @@
private final Object closeLock = new Object();
private volatile boolean closed = false;
+ private final CloseGuard guard = CloseGuard.get();
+ private final boolean isFdOwner;
+
/**
* Creates a file output stream to write to the file with the
* specified name. A new <code>FileDescriptor</code> object is
@@ -209,8 +215,11 @@
this.fd = new FileDescriptor();
this.append = append;
this.path = name;
- fd.incrementAndGetUseCount();
+ this.isFdOwner = true;
+
+ BlockGuard.getThreadPolicy().onWriteToDisk();
open(name, append);
+ guard.open("close");
}
/**
@@ -254,13 +263,7 @@
this.fd = fdObj;
this.path = null;
this.append = false;
-
- /*
- * FileDescriptor is being shared by streams.
- * Ensure that it's GC'ed only when all the streams/channels are done
- * using it.
- */
- fd.incrementAndGetUseCount();
+ this.isFdOwner = isFdOwner;
}
/**
@@ -338,27 +341,19 @@
closed = true;
}
+ guard.close();
+
if (channel != null) {
/*
* Decrement FD use count associated with the channel
* The use count is incremented whenever a new channel
* is obtained from this stream.
*/
- fd.decrementAndGetUseCount();
channel.close();
}
- /*
- * Decrement FD use count associated with this stream
- */
- int useCount = fd.decrementAndGetUseCount();
- /*
- * If FileDescriptor is still in use by another stream, the finalizer
- * will not close it.
- */
- // Android change, make sure only last close closes FD.
- if ((useCount <= 0)) {
+ if (isFdOwner) {
IoBridge.closeAndSignalBlockedThreads(fd);
}
}
@@ -399,13 +394,6 @@
synchronized (this) {
if (channel == null) {
channel = FileChannelImpl.open(fd, path, false, true, append, this);
-
- /*
- * Increment fd's use count. Invoking the channel's close()
- * method will result in decrementing the use count set for
- * the channel.
- */
- fd.incrementAndGetUseCount();
}
return channel;
}
@@ -420,6 +408,10 @@
* @see java.io.FileInputStream#close()
*/
protected void finalize() throws IOException {
+ if (guard != null) {
+ guard.warnIfOpen();
+ }
+
if (fd != null) {
if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
flush();
diff --git a/ojluni/src/main/java/java/io/RandomAccessFile.java b/ojluni/src/main/java/java/io/RandomAccessFile.java
index d7c26f6..6008d0f 100755
--- a/ojluni/src/main/java/java/io/RandomAccessFile.java
+++ b/ojluni/src/main/java/java/io/RandomAccessFile.java
@@ -290,16 +290,6 @@
synchronized (this) {
if (channel == null) {
channel = FileChannelImpl.open(fd, path, true, rw, this);
- /*
- * FileDescriptor could be shared by FileInputStream or
- * FileOutputStream.
- * Ensure that FD is GC'ed only when all the streams/channels
- * are done using it.
- * Increment fd's use count. Invoking the channel's close()
- * method will result in decrementing the use count set for
- * the channel.
- */
- // fd.incrementAndGetUseCount();
}
return channel;
}
diff --git a/ojluni/src/main/java/java/io/UnixFileSystem.java b/ojluni/src/main/java/java/io/UnixFileSystem.java
index c2b39b8..60777f6 100755
--- a/ojluni/src/main/java/java/io/UnixFileSystem.java
+++ b/ojluni/src/main/java/java/io/UnixFileSystem.java
@@ -26,6 +26,8 @@
package java.io;
import java.security.AccessController;
+
+import dalvik.system.BlockGuard;
import sun.security.action.GetPropertyAction;
@@ -169,6 +171,7 @@
}
}
if (res == null) {
+ BlockGuard.getThreadPolicy().onReadFromDisk();
res = canonicalize0(path);
cache.put(path, res);
if (useCanonPrefixCache &&
@@ -236,29 +239,54 @@
/* -- Attribute accessors -- */
- /* ----- BEGIN android -----
- public native int getBooleanAttributes0(File f);*/
- public native int getBooleanAttributes0(String abspath);
+ private native int getBooleanAttributes0(String abspath);
public int getBooleanAttributes(File f) {
- /* ----- BEGIN android -----
- int rv = getBooleanAttributes0(f);*/
+ BlockGuard.getThreadPolicy().onReadFromDisk();
+
int rv = getBooleanAttributes0(f.getPath());
- // ----- END android -----
String name = f.getName();
boolean hidden = (name.length() > 0) && (name.charAt(0) == '.');
return rv | (hidden ? BA_HIDDEN : 0);
}
- public native boolean checkAccess(File f, int access);
- public native long getLastModifiedTime(File f);
- public native long getLength(File f);
- public native boolean setPermission(File f, int access, boolean enable, boolean owneronly);
+ public boolean checkAccess(File f, int access) {
+ BlockGuard.getThreadPolicy().onReadFromDisk();
+ return checkAccess0(f, access);
+ }
+
+ private native boolean checkAccess0(File f, int access);
+
+ public long getLastModifiedTime(File f) {
+ BlockGuard.getThreadPolicy().onReadFromDisk();
+ return getLastModifiedTime0(f);
+ }
+
+ private native long getLastModifiedTime0(File f);
+
+ public long getLength(File f) {
+ BlockGuard.getThreadPolicy().onReadFromDisk();
+ return getLength0(f);
+ }
+
+ private native long getLength0(File f);
+
+ 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 -- */
- public native boolean createFileExclusively(String path)
- throws IOException;
+ public boolean createFileExclusively(String path) throws IOException {
+ BlockGuard.getThreadPolicy().onWriteToDisk();
+ return createFileExclusively0(path);
+ }
+
+ private native boolean createFileExclusively0(String path) throws IOException;
+
public boolean delete(File f) {
// Keep canonicalization caches in sync after file deletion
// and renaming operations. Could be more clever than this
@@ -267,11 +295,26 @@
// anyway.
cache.clear();
javaHomePrefixCache.clear();
+ BlockGuard.getThreadPolicy().onWriteToDisk();
return delete0(f);
}
+
private native boolean delete0(File f);
- public native String[] list(File f);
- public native boolean createDirectory(File f);
+
+ public String[] list(File f) {
+ BlockGuard.getThreadPolicy().onReadFromDisk();
+ return list0(f);
+ }
+
+ private native String[] list0(File f);
+
+ public boolean createDirectory(File f) {
+ BlockGuard.getThreadPolicy().onWriteToDisk();
+ return createDirectory0(f);
+ }
+
+ private native boolean createDirectory0(File f);
+
public boolean rename(File f1, File f2) {
// Keep canonicalization caches in sync after file deletion
// and renaming operations. Could be more clever than this
@@ -280,11 +323,25 @@
// anyway.
cache.clear();
javaHomePrefixCache.clear();
+ BlockGuard.getThreadPolicy().onWriteToDisk();
return rename0(f1, f2);
}
+
private native boolean rename0(File f1, File f2);
- public native boolean setLastModifiedTime(File f, long time);
- public native boolean setReadOnly(File f);
+
+ public boolean setLastModifiedTime(File f, long time) {
+ BlockGuard.getThreadPolicy().onWriteToDisk();
+ return setLastModifiedTime0(f, time);
+ }
+
+ private native boolean setLastModifiedTime0(File f, long time);
+
+ public boolean setReadOnly(File f) {
+ BlockGuard.getThreadPolicy().onWriteToDisk();
+ return setReadOnly0(f);
+ }
+
+ private native boolean setReadOnly0(File f);
/* -- Filesystem interface -- */
@@ -302,7 +359,13 @@
}
/* -- Disk usage -- */
- public native long getSpace(File f, int t);
+ 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/net/AbstractPlainDatagramSocketImpl.java b/ojluni/src/main/java/java/net/AbstractPlainDatagramSocketImpl.java
index 57394f4..e7ad94c 100755
--- a/ojluni/src/main/java/java/net/AbstractPlainDatagramSocketImpl.java
+++ b/ojluni/src/main/java/java/net/AbstractPlainDatagramSocketImpl.java
@@ -29,6 +29,9 @@
import java.io.InterruptedIOException;
import java.util.Enumeration;
import java.security.AccessController;
+
+import dalvik.system.BlockGuard;
+import dalvik.system.CloseGuard;
import sun.net.ResourceManager;
/**
@@ -55,6 +58,8 @@
private boolean loopbackMode = true;
private int ttl = -1;
+ private final CloseGuard guard = CloseGuard.get();
+
private static final String os = AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("os.name")
);
@@ -77,6 +82,10 @@
fd = null;
throw ioe;
}
+
+ if (fd != null && fd.valid()) {
+ guard.open("close");
+ }
}
/**
@@ -105,6 +114,7 @@
* @param port the remote port number
*/
protected void connect(InetAddress address, int port) throws SocketException {
+ BlockGuard.getThreadPolicy().onNetwork();
connect0(address, port);
connectedAddress = address;
connectedPort = port;
@@ -124,13 +134,13 @@
/**
* Peek at the packet to see who it is from.
- * @param return the address which the packet came from.
+ * @return the address which the packet came from.
*/
protected abstract int peek(InetAddress i) throws IOException;
protected abstract int peekData(DatagramPacket p) throws IOException;
/**
* Receive the datagram packet.
- * @param Packet Received.
+ * @param p Packet Received.
*/
protected synchronized void receive(DatagramPacket p)
throws IOException {
@@ -142,7 +152,7 @@
/**
* Set the TTL (time-to-live) option.
- * @param TTL to be set.
+ * @param ttl the TTL to be set.
*/
protected abstract void setTimeToLive(int ttl) throws IOException;
@@ -153,7 +163,7 @@
/**
* Set the TTL (time-to-live) option.
- * @param TTL to be set.
+ * @param ttl the TTL to be set.
*/
protected abstract void setTTL(byte ttl) throws IOException;
@@ -164,7 +174,7 @@
/**
* Join the multicast group.
- * @param multicast address to join.
+ * @param inetaddr multicast address to join.
*/
protected void join(InetAddress inetaddr) throws IOException {
join(inetaddr, null);
@@ -172,14 +182,14 @@
/**
* Leave the multicast group.
- * @param multicast address to leave.
+ * @param inetaddr multicast address to leave.
*/
protected void leave(InetAddress inetaddr) throws IOException {
leave(inetaddr, null);
}
/**
* Join the multicast group.
- * @param multicast address to join.
+ * @param mcastaddr multicast address to join.
* @param netIf specifies the local interface to receive multicast
* datagram packets
* @throws IllegalArgumentException if mcastaddr is null or is a
@@ -199,7 +209,7 @@
/**
* Leave the multicast group.
- * @param multicast address to leave.
+ * @param mcastaddr multicast address to leave.
* @param netIf specified the local interface to leave the group at
* @throws IllegalArgumentException if mcastaddr is null or is a
* SocketAddress subclass not supported by this socket
@@ -219,6 +229,8 @@
* Close the socket.
*/
protected void close() {
+ guard.close();
+
if (fd != null) {
datagramSocketClose();
ResourceManager.afterUdpClose();
@@ -231,6 +243,10 @@
}
protected void finalize() {
+ if (guard != null) {
+ guard.warnIfOpen();
+ }
+
close();
}
diff --git a/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java b/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java
index 8cd9add..920531a 100755
--- a/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java
+++ b/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java
@@ -31,6 +31,8 @@
import java.io.OutputStream;
import java.io.FileDescriptor;
+import dalvik.system.BlockGuard;
+import dalvik.system.CloseGuard;
import sun.net.ConnectionResetException;
import sun.net.NetHooks;
import sun.net.ResourceManager;
@@ -71,6 +73,8 @@
*/
protected boolean stream;
+ private final CloseGuard guard = CloseGuard.get();
+
/**
* Creates a socket with a boolean that specifies whether this
* is a stream socket (true) or an unconnected UDP socket (false).
@@ -94,6 +98,11 @@
socket.setCreated();
if (serverSocket != null)
serverSocket.setCreated();
+
+ // socketCreate will set |fd| if it succeeds.
+ if (fd != null && fd.valid()) {
+ guard.open("close");
+ }
}
/**
@@ -322,6 +331,7 @@
}
}
try {
+ BlockGuard.getThreadPolicy().onNetwork();
socketConnect(address, port, timeout);
/* socket may have been closed during poll/select */
synchronized (fdLock) {
@@ -346,7 +356,7 @@
/**
* Binds the socket to the specified address of the specified local port.
* @param address the address
- * @param port the port
+ * @param lport the port
*/
protected synchronized void bind(InetAddress address, int lport)
throws IOException
@@ -376,6 +386,7 @@
* @param s the connection
*/
protected void accept(SocketImpl s) throws IOException {
+ BlockGuard.getThreadPolicy().onNetwork();
socketAccept(s);
}
@@ -537,6 +548,10 @@
* Cleans up if the user forgets to close it.
*/
protected void finalize() throws IOException {
+ if (guard != null) {
+ guard.warnIfOpen();
+ }
+
close();
}
@@ -576,7 +591,6 @@
resetState = CONNECTION_RESET_PENDING;
}
}
-
}
/*
@@ -607,6 +621,8 @@
* Close the socket (and release the file descriptor).
*/
protected void socketClose() throws IOException {
+ guard.close();
+
socketClose0();
}
diff --git a/ojluni/src/main/java/java/net/Inet4Address.java b/ojluni/src/main/java/java/net/Inet4Address.java
index 8f869ed..5e90067 100755
--- a/ojluni/src/main/java/java/net/Inet4Address.java
+++ b/ojluni/src/main/java/java/net/Inet4Address.java
@@ -332,6 +332,7 @@
return addr;
}
+ @Override
public byte[] getAddressInternal() {
return getAddress();
}
diff --git a/ojluni/src/main/java/java/net/Inet6Address.java b/ojluni/src/main/java/java/net/Inet6Address.java
index dd4dd19..d40dff0 100755
--- a/ojluni/src/main/java/java/net/Inet6Address.java
+++ b/ojluni/src/main/java/java/net/Inet6Address.java
@@ -622,6 +622,7 @@
return ipaddress.clone();
}
+ @Override
public byte[] getAddressInternal() {
return ipaddress;
}
diff --git a/ojluni/src/main/java/java/net/Inet6AddressImpl.java b/ojluni/src/main/java/java/net/Inet6AddressImpl.java
index 9e2806d..b40e98c 100755
--- a/ojluni/src/main/java/java/net/Inet6AddressImpl.java
+++ b/ojluni/src/main/java/java/net/Inet6AddressImpl.java
@@ -24,26 +24,126 @@
* questions.
*/
package java.net;
+import android.system.ErrnoException;
+import android.system.GaiException;
+import android.system.StructAddrinfo;
+import dalvik.system.BlockGuard;
+import libcore.io.Libcore;
+
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.SOCK_STREAM;
+
/*
* Package private implementation of InetAddressImpl for dual
- * IPv4/IPv6 stack.
- * <p>
- * If InetAddress.preferIPv6Address is true then anyLocalAddress(),
- * loopbackAddress(), and localHost() will return IPv6 addresses,
- * otherwise IPv4 addresses.
+ * IPv4/IPv6 stack. {@code #anyLocalAddress()} will always return an IPv6 address.
*
* @since 1.4
*/
class Inet6AddressImpl implements InetAddressImpl {
- public native String getLocalHostName() throws UnknownHostException;
- public native InetAddress[]
- lookupAllHostAddr(String hostname) throws UnknownHostException;
- public native String getHostByAddr(byte[] addr) throws UnknownHostException;
- private native boolean isReachable0(byte[] addr, int scope, int timeout, byte[] inf, int ttl, int if_scope) throws IOException;
+ private static final InetAddress ANY_LOCAL_ADDRESS;
+ private static final InetAddress[] LOOPBACK_ADDRESSES;
+
+ static {
+ ANY_LOCAL_ADDRESS = new Inet6Address();
+ ANY_LOCAL_ADDRESS.holder().hostName = "::";
+
+ LOOPBACK_ADDRESSES = new InetAddress[] { Inet6Address.LOOPBACK, Inet4Address.LOOPBACK };
+ }
+
+ private static final AddressCache addressCache = new AddressCache();
+
+ @Override
+ public InetAddress[] lookupAllHostAddr(String host, int netId) throws UnknownHostException {
+ if (host == null || host.isEmpty()) {
+ // Android-changed : Return both the Inet4 and Inet6 loopback addresses
+ // when host == null or empty.
+ return loopbackAddresses();
+ }
+
+ // Is it a numeric address?
+ InetAddress result = InetAddress.parseNumericAddressNoThrow(host);
+ if (result != null) {
+ result = InetAddress.disallowDeprecatedFormats(host, result);
+ if (result == null) {
+ throw new UnknownHostException("Deprecated IPv4 address format: " + host);
+ }
+ return new InetAddress[] { result };
+ }
+
+ return lookupHostByName(host, netId).clone();
+ }
+
+ /**
+ * Resolves a hostname to its IP addresses using a cache.
+ *
+ * @param host the hostname to resolve.
+ * @param netId the network to perform resolution upon.
+ * @return the IP addresses of the host.
+ */
+ private static InetAddress[] lookupHostByName(String host, int netId)
+ throws UnknownHostException {
+ BlockGuard.getThreadPolicy().onNetwork();
+ // Do we have a result cached?
+ Object cachedResult = addressCache.get(host, netId);
+ if (cachedResult != null) {
+ if (cachedResult instanceof InetAddress[]) {
+ // A cached positive result.
+ return (InetAddress[]) cachedResult;
+ } else {
+ // A cached negative result.
+ throw new UnknownHostException((String) cachedResult);
+ }
+ }
+ try {
+ StructAddrinfo hints = new StructAddrinfo();
+ hints.ai_flags = AI_ADDRCONFIG;
+ hints.ai_family = AF_UNSPEC;
+ // If we don't specify a socket type, every address will appear twice, once
+ // for SOCK_STREAM and one for SOCK_DGRAM. Since we do not return the family
+ // anyway, just pick one.
+ hints.ai_socktype = SOCK_STREAM;
+ InetAddress[] addresses = Libcore.os.android_getaddrinfo(host, hints, netId);
+ // TODO: should getaddrinfo set the hostname of the InetAddresses it returns?
+ for (InetAddress address : addresses) {
+ address.holder().hostName = host;
+ }
+ addressCache.put(host, netId, addresses);
+ return addresses;
+ } catch (GaiException gaiException) {
+ // If the failure appears to have been a lack of INTERNET permission, throw a clear
+ // SecurityException to aid in debugging this common mistake.
+ // http://code.google.com/p/android/issues/detail?id=15722
+ if (gaiException.getCause() instanceof ErrnoException) {
+ if (((ErrnoException) gaiException.getCause()).errno == EACCES) {
+ throw new SecurityException("Permission denied (missing INTERNET permission?)", gaiException);
+ }
+ }
+ // Otherwise, throw an UnknownHostException.
+ String detailMessage = "Unable to resolve host \"" + host + "\": " + Libcore.os.gai_strerror(gaiException.error);
+ addressCache.putUnknownHost(host, netId, detailMessage);
+ throw gaiException.rethrowAsUnknownHostException(detailMessage);
+ }
+ }
+
+ @Override
+ public String getHostByAddr(byte[] addr) throws UnknownHostException {
+ BlockGuard.getThreadPolicy().onNetwork();
+
+ return getHostByAddr0(addr);
+ }
+
+ @Override
+ public void clearAddressCache() {
+ addressCache.clear();
+ }
+
+ @Override
public boolean isReachable(InetAddress addr, int timeout, NetworkInterface netif, int ttl) throws IOException {
byte[] ifaddr = null;
int scope = -1;
@@ -75,27 +175,21 @@
}
if (addr instanceof Inet6Address)
scope = ((Inet6Address) addr).getScopeId();
+
+ BlockGuard.getThreadPolicy().onNetwork();
return isReachable0(addr.getAddress(), scope, timeout, ifaddr, ttl, netif_scope);
}
- public synchronized InetAddress anyLocalAddress() {
- if (anyLocalAddress == null) {
- anyLocalAddress = new Inet6Address();
- anyLocalAddress.holder().hostName = "::";
- }
- return anyLocalAddress;
+ @Override
+ public InetAddress anyLocalAddress() {
+ return ANY_LOCAL_ADDRESS;
}
- public synchronized InetAddress loopbackAddress() {
- if (loopbackAddress == null) {
- byte[] loopback =
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
- loopbackAddress = new Inet6Address("localhost", loopback);
- }
- return loopbackAddress;
+ @Override
+ public InetAddress[] loopbackAddresses() {
+ return LOOPBACK_ADDRESSES;
}
- private InetAddress anyLocalAddress;
- private InetAddress loopbackAddress;
+ 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/net/InetAddress.java b/ojluni/src/main/java/java/net/InetAddress.java
index b5af719..d86c3d3 100755
--- a/ojluni/src/main/java/java/net/InetAddress.java
+++ b/ojluni/src/main/java/java/net/InetAddress.java
@@ -26,14 +26,6 @@
package java.net;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Random;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ArrayList;
-import java.security.AccessController;
import java.io.ObjectStreamException;
import java.io.ObjectStreamField;
import java.io.IOException;
@@ -41,15 +33,10 @@
import java.io.ObjectInputStream.GetField;
import java.io.ObjectOutputStream;
import java.io.ObjectOutputStream.PutField;
-import java.net.AddressCache;
-import sun.security.action.*;
import sun.net.util.IPAddressUtil;
-import sun.misc.Service;
import sun.net.spi.nameservice.*;
-import android.system.ErrnoException;
import android.system.GaiException;
import android.system.StructAddrinfo;
-import dalvik.system.BlockGuard;
import libcore.io.Libcore;
import static android.system.OsConstants.*;
@@ -195,23 +182,6 @@
*/
public
class InetAddress implements java.io.Serializable {
- /* ----- BEGIN android -----
- Use AF_INET for IPv4 and AF_INET6 for IPv6 (and AF_UNIX for unix sockets)
- //
- // Specify the address family: Internet Protocol, Version 4
- // @since 1.4
- //
- static final int IPv4 = 1;
-
- //
- // Specify the address family: Internet Protocol, Version 6
- // @since 1.4
- //
- static final int IPv6 = 2;
- ----- END android ----- */
-
- /* Specify address family preference */
- static transient boolean preferIPv6Address = false;
static class InetAddressHolder {
@@ -249,14 +219,26 @@
}
}
- final transient InetAddressHolder holder;
+ transient InetAddressHolder holder;
InetAddressHolder holder() {
return holder;
}
+ /* The implementation is always dual stack IPv6/IPv4 on android */
+ static final InetAddressImpl impl = new Inet6AddressImpl();
+
/* Used to store the name service provider */
- private static List<NameService> nameServices = null;
+ private static final NameService nameService = new NameService() {
+ public InetAddress[] lookupAllHostAddr(String host, int netId)
+ throws UnknownHostException {
+ return impl.lookupAllHostAddr(host, netId);
+ }
+ public String getHostByAddr(byte[] addr)
+ throws UnknownHostException {
+ return impl.getHostByAddr(addr);
+ }
+ };
/* Used to store the best available hostname */
private transient String canonicalHostName = null;
@@ -268,8 +250,6 @@
* Load net library into runtime, and perform initializations.
*/
static {
- preferIPv6Address = java.security.AccessController.doPrivileged(
- new GetBooleanAction("java.net.preferIPv6Addresses")).booleanValue();
init();
}
@@ -433,7 +413,7 @@
* @since 1.5
*/
public boolean isReachable(int timeout) throws IOException {
- return isReachable(null, 0 , timeout);
+ return isReachable(null, 0, timeout);
}
/**
@@ -503,35 +483,8 @@
* @see SecurityManager#checkConnect
*/
public String getHostName() {
- return getHostName(true);
- }
-
- /**
- * Returns the hostname for this address.
- * If the host is equal to null, then this address refers to any
- * of the local machine's available network addresses.
- * this is package private so SocketPermission can make calls into
- * here without a security check.
- *
- * <p>If there is a security manager, this method first
- * calls its <code>checkConnect</code> method
- * with the hostname and <code>-1</code>
- * as its arguments to see if the calling code is allowed to know
- * the hostname for this IP address, i.e., to connect to the host.
- * If the operation is not allowed, it will return
- * the textual representation of the IP address.
- *
- * @return the host name for this IP address, or if the operation
- * is not allowed by the security check, the textual
- * representation of the IP address.
- *
- * @param check make security check if true
- *
- * @see SecurityManager#checkConnect
- */
- String getHostName(boolean check) {
if (holder().getHostName() == null) {
- holder().hostName = InetAddress.getHostFromNameService(this, check);
+ holder().hostName = InetAddress.getHostFromNameService(this);
}
return holder().getHostName();
}
@@ -559,8 +512,7 @@
*/
public String getCanonicalHostName() {
if (canonicalHostName == null) {
- canonicalHostName =
- InetAddress.getHostFromNameService(this, true);
+ canonicalHostName = InetAddress.getHostFromNameService(this);
}
return canonicalHostName;
}
@@ -580,56 +532,34 @@
* is not allowed by the security check, the textual
* representation of the IP address.
*
- * @param check make security check if true
- *
* @see SecurityManager#checkConnect
*/
- private static String getHostFromNameService(InetAddress addr, boolean check) {
+ private static String getHostFromNameService(InetAddress addr) {
String host = null;
- for (NameService nameService : nameServices) {
- try {
- // first lookup the hostname
- host = nameService.getHostByAddr(addr.getAddress());
-
- /* check to see if calling code is allowed to know
- * the hostname for this IP address, ie, connect to the host
- */
- if (check) {
- SecurityManager sec = System.getSecurityManager();
- if (sec != null) {
- sec.checkConnect(host, -1);
- }
- }
+ try {
+ // first lookup the hostname
+ host = nameService.getHostByAddr(addr.getAddress());
/* now get all the IP addresses for this hostname,
* and make sure one of them matches the original IP
* address. We do this to try and prevent spoofing.
*/
+ InetAddress[] arr = nameService.lookupAllHostAddr(host, NETID_UNSET);
+ boolean ok = false;
- InetAddress[] arr = InetAddress.getAllByName0(host, check);
- boolean ok = false;
-
- if(arr != null) {
- for(int i = 0; !ok && i < arr.length; i++) {
- ok = addr.equals(arr[i]);
- }
+ if (arr != null) {
+ for(int i = 0; !ok && i < arr.length; i++) {
+ ok = addr.equals(arr[i]);
}
-
- //XXX: if it looks a spoof just return the address?
- if (!ok) {
- host = addr.getHostAddress();
- return host;
- }
-
- break;
-
- } catch (SecurityException e) {
- host = addr.getHostAddress();
- break;
- } catch (UnknownHostException e) {
- host = addr.getHostAddress();
- // let next provider resolve the hostname
}
+
+ //XXX: if it looks a spoof just return the address?
+ if (!ok) {
+ host = addr.getHostAddress();
+ return host;
+ }
+ } catch (UnknownHostException e) {
+ host = addr.getHostAddress();
}
return host;
@@ -646,11 +576,16 @@
return null;
}
- /* @hide */
+ /**
+ * Called from native code. Same as {@code getAddress}, but for internal users.
+ *
+ * @return
+ */
public byte[] getAddressInternal() {
return null;
}
+
/**
* Returns the IP address string in textual presentation.
*
@@ -706,91 +641,6 @@
+ "/" + getHostAddress();
}
- static InetAddressImpl impl;
- private static final AddressCache addressCache = new AddressCache();
-
-
- private static NameService createNSProvider(String provider) {
- if (provider == null)
- return null;
-
- NameService nameService = null;
- if (provider.equals("default")) {
- // initialize the default name service
- nameService = new NameService() {
- public InetAddress[] lookupAllHostAddr(String host)
- throws UnknownHostException {
- return impl.lookupAllHostAddr(host);
- }
- public String getHostByAddr(byte[] addr)
- throws UnknownHostException {
- return impl.getHostByAddr(addr);
- }
- };
- } else {
- final String providerName = provider;
- try {
- nameService = java.security.AccessController.doPrivileged(
- new java.security.PrivilegedExceptionAction<NameService>() {
- public NameService run() {
- Iterator itr = Service.providers(NameServiceDescriptor.class);
- while (itr.hasNext()) {
- NameServiceDescriptor nsd
- = (NameServiceDescriptor)itr.next();
- if (providerName.
- equalsIgnoreCase(nsd.getType()+","
- +nsd.getProviderName())) {
- try {
- return nsd.createNameService();
- } catch (Exception e) {
- e.printStackTrace();
- System.err.println(
- "Cannot create name service:"
- +providerName+": " + e);
- }
- }
- }
-
- return null;
- }
- }
- );
- } catch (java.security.PrivilegedActionException e) {
- }
- }
-
- return nameService;
- }
-
- static {
- // create the impl
- impl = InetAddressImplFactory.create();
-
- // get name service if provided and requested
- String provider = null;;
- String propPrefix = "sun.net.spi.nameservice.provider.";
- int n = 1;
- nameServices = new ArrayList<NameService>();
- provider = AccessController.doPrivileged(
- new GetPropertyAction(propPrefix + n));
- while (provider != null) {
- NameService ns = createNSProvider(provider);
- if (ns != null)
- nameServices.add(ns);
-
- n++;
- provider = AccessController.doPrivileged(
- new GetPropertyAction(propPrefix + n));
- }
-
- // if not designate any name services provider,
- // create a default one
- if (nameServices.size() == 0) {
- NameService ns = createNSProvider("default");
- nameServices.add(ns);
- }
- }
-
/**
* Creates an InetAddress based on the provided host name and IP address.
* No name service is checked for the validity of the address.
@@ -813,29 +663,11 @@
* @exception UnknownHostException if IP address is of illegal length
* @since 1.4
*/
- public static InetAddress getByAddress(String host, byte[] addr)
- throws UnknownHostException {
- if (host != null && host.length() > 0 && host.charAt(0) == '[') {
- if (host.charAt(host.length()-1) == ']') {
- host = host.substring(1, host.length() -1);
- }
- }
- if (addr != null) {
- if (addr.length == Inet4Address.INADDRSZ) {
- return new Inet4Address(host, addr);
- } else if (addr.length == Inet6Address.INADDRSZ) {
- byte[] newAddr
- = IPAddressUtil.convertFromIPv4MappedAddress(addr);
- if (newAddr != null) {
- return new Inet4Address(host, newAddr);
- } else {
- return new Inet6Address(host, addr);
- }
- }
- }
- throw new UnknownHostException("addr is of illegal length");
+ public static InetAddress getByAddress(String host, byte[] addr) throws UnknownHostException {
+ return getByAddress(host, addr, -1 /* scopeId */);
}
+ // Do not delete. Called from native code.
private static InetAddress getByAddress(String host, byte[] addr, int scopeId)
throws UnknownHostException {
if (host != null && host.length() > 0 && host.charAt(0) == '[') {
@@ -893,12 +725,6 @@
return InetAddress.getAllByName(host)[0];
}
- // called from deployment cache manager
- private static InetAddress getByName(String host, InetAddress reqAddr)
- throws UnknownHostException {
- return InetAddress.getAllByName(host, reqAddr)[0];
- }
-
/**
* Given the name of a host, returns an array of its IP addresses,
* based on the configured name service on the system.
@@ -940,26 +766,7 @@
*/
public static InetAddress[] getAllByName(String host)
throws UnknownHostException {
- return getAllByName(host, null);
- }
-
- private static InetAddress[] getAllByName(String host, InetAddress reqAddr)
- throws UnknownHostException {
-
- if (host == null || host.length() == 0) {
- // Android-changed : Return both the Inet4 and Inet6 loopback addresses
- // when host == null or empty.
- return loopbackAddresses();
- }
-
- // if host is an IP address, we won't do further lookup
- try {
- return new InetAddress[] { parseNumericAddress(host) };
- } catch (IllegalArgumentException e) {
- // This is not an IP address, continue to lookup by host name.
- }
-
- return getAllByName0(host, reqAddr, true);
+ return impl.lookupAllHostAddr(host, NETID_UNSET);
}
/**
@@ -974,77 +781,7 @@
* @since 1.7
*/
public static InetAddress getLoopbackAddress() {
- return impl.loopbackAddress();
- }
-
-
- /**
- * check if the literal address string has %nn appended
- * returns -1 if not, or the numeric value otherwise.
- *
- * %nn may also be a string that represents the displayName of
- * a currently available NetworkInterface.
- */
- private static int checkNumericZone (String s) throws UnknownHostException {
- int percent = s.indexOf ('%');
- int slen = s.length();
- int digit, zone=0;
- if (percent == -1) {
- return -1;
- }
- for (int i=percent+1; i<slen; i++) {
- char c = s.charAt(i);
- if (c == ']') {
- if (i == percent+1) {
- /* empty per-cent field */
- return -1;
- }
- break;
- }
- if ((digit = Character.digit (c, 10)) < 0) {
- return -1;
- }
- zone = (zone * 10) + digit;
- }
- return zone;
- }
-
- private static InetAddress[] getAllByName0 (String host)
- throws UnknownHostException
- {
- return getAllByName0(host, true);
- }
-
- /**
- * package private so SocketPermission can call it
- */
- static InetAddress[] getAllByName0 (String host, boolean check)
- throws UnknownHostException {
- return getAllByName0 (host, null, check);
- }
-
- private static InetAddress[] getAllByName0 (String host, InetAddress reqAddr, boolean check)
- throws UnknownHostException {
- return getAllByName0(host, reqAddr, NETID_UNSET, check);
- }
-
- private static InetAddress[] getAllByName0 (String host, InetAddress reqAddr, int netId, boolean check)
- throws UnknownHostException {
-
- /* If it gets here it is presumed to be a hostname */
- /* Cache.get can return: null, unknownAddress, or InetAddress[] */
-
- /* make sure the connection to the host is allowed, before we
- * give out a hostname
- */
- if (check) {
- SecurityManager security = System.getSecurityManager();
- if (security != null) {
- security.checkConnect(host, -1);
- }
- }
-
- return lookupHostByName(host, netId);
+ return impl.loopbackAddresses()[0];
}
/**
@@ -1068,11 +805,6 @@
return getByAddress(null, addr);
}
- private static InetAddress cachedLocalHost = null;
- private static long cacheTime = 0;
- private static final long maxCacheTime = 5000L;
- private static final Object cacheLock = new Object();
-
/**
* Returns the address of the local host. This is achieved by retrieving
* the name of the host from the system, then resolving that name into
@@ -1097,18 +829,8 @@
* @see java.net.InetAddress#getByName(java.lang.String)
*/
public static InetAddress getLocalHost() throws UnknownHostException {
-
- SecurityManager security = System.getSecurityManager();
- try {
- String local = Libcore.os.uname().nodename;
- if (security != null) {
- security.checkConnect(local, -1);
- }
-
- return lookupHostByName(local, NETID_UNSET)[0];
- } catch (java.lang.SecurityException e) {
- return impl.loopbackAddress();
- }
+ String local = Libcore.os.uname().nodename;
+ return impl.lookupAllHostAddr(local, NETID_UNSET)[0];
}
/**
@@ -1125,48 +847,6 @@
return impl.anyLocalAddress();
}
- /*
- * Load and instantiate an underlying impl class
- */
- static InetAddressImpl loadImpl(String implName) {
- Object impl = null;
-
- /*
- * Property "impl.prefix" will be prepended to the classname
- * of the implementation object we instantiate, to which we
- * delegate the real work (like native methods). This
- * property can vary across implementations of the java.
- * classes. The default is an empty String "".
- */
- String prefix = AccessController.doPrivileged(
- new GetPropertyAction("impl.prefix", ""));
- try {
- impl = Class.forName("java.net." + prefix + implName).newInstance();
- } catch (ClassNotFoundException e) {
- System.err.println("Class not found: java.net." + prefix +
- implName + ":\ncheck impl.prefix property " +
- "in your properties file.");
- } catch (InstantiationException e) {
- System.err.println("Could not instantiate: java.net." + prefix +
- implName + ":\ncheck impl.prefix property " +
- "in your properties file.");
- } catch (IllegalAccessException e) {
- System.err.println("Cannot access class: java.net." + prefix +
- implName + ":\ncheck impl.prefix property " +
- "in your properties file.");
- }
-
- if (impl == null) {
- try {
- impl = Class.forName(implName).newInstance();
- } catch (Exception e) {
- throw new Error("System property impl.prefix incorrect");
- }
- }
-
- return (InetAddressImpl) impl;
- }
-
private void readObjectNoData (ObjectInputStream s) throws
IOException, ClassNotFoundException {
// Android-changed : Don't use null to mean the boot classloader.
@@ -1175,24 +855,8 @@
}
}
- private static final long FIELDS_OFFSET;
- private static final sun.misc.Unsafe UNSAFE;
// Android-changed : Don't use null to mean the boot classloader.
- private static final ClassLoader BOOT_CLASSLOADER;
-
- static {
- try {
- sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
- FIELDS_OFFSET = unsafe.objectFieldOffset(
- InetAddress.class.getDeclaredField("holder")
- );
- UNSAFE = unsafe;
- } catch (ReflectiveOperationException e) {
- throw new Error(e);
- }
-
- BOOT_CLASSLOADER = Class.class.getClassLoader();
- }
+ private static final ClassLoader BOOT_CLASSLOADER = Object.class.getClassLoader();
private void readObject (ObjectInputStream s) throws
IOException, ClassNotFoundException {
@@ -1204,8 +868,7 @@
String host = (String)gf.get("hostName", null);
int address= gf.get("address", 0);
int family= gf.get("family", 0);
- InetAddressHolder h = new InetAddressHolder(host, address, family);
- UNSAFE.putObject(this, FIELDS_OFFSET, h);
+ holder = new InetAddressHolder(host, address, family);
}
/* needed because the serializable fields no longer exist */
@@ -1235,7 +898,7 @@
s.flush();
}
- private static final int NETID_UNSET = 0;
+ static final int NETID_UNSET = 0;
/**
* Returns true if the string is a valid numeric IPv4 or IPv6 address (such as "192.168.0.1").
@@ -1249,7 +912,7 @@
return inetAddress != null && disallowDeprecatedFormats(address, inetAddress) != null;
}
- private static InetAddress parseNumericAddressNoThrow(String address) {
+ static InetAddress parseNumericAddressNoThrow(String address) {
// Accept IPv6 addresses (only) in square brackets for compatibility.
if (address.startsWith("[") && address.endsWith("]") && address.indexOf(':') != -1) {
address = address.substring(1, address.length() - 1);
@@ -1264,7 +927,7 @@
return (addresses != null) ? addresses[0] : null;
}
- private static InetAddress disallowDeprecatedFormats(String address, InetAddress inetAddress) {
+ static InetAddress disallowDeprecatedFormats(String address, InetAddress inetAddress) {
// Only IPv4 addresses are problematic.
if (!(inetAddress instanceof Inet4Address) || address.indexOf(':') != -1) {
return inetAddress;
@@ -1301,7 +964,7 @@
* @hide
*/
public static void clearDnsCache() {
- addressCache.clear();
+ impl.clearAddressCache();
}
/**
@@ -1316,7 +979,7 @@
* @hide internal use only
*/
public static InetAddress getByNameOnNet(String host, int netId) throws UnknownHostException {
- return getAllByNameImpl(host, netId)[0];
+ return impl.lookupAllHostAddr(host, netId)[0];
}
/**
@@ -1330,95 +993,16 @@
* @hide internal use only
*/
public static InetAddress[] getAllByNameOnNet(String host, int netId) throws UnknownHostException {
- return getAllByNameImpl(host, netId).clone();
+ return impl.lookupAllHostAddr(host, netId).clone();
}
- /**
- * Returns the InetAddresses for {@code host} on network {@code netId}. The
- * returned array is shared and must be cloned before it is returned to
- * application code.
- */
- private static InetAddress[] getAllByNameImpl(String host, int netId) throws UnknownHostException {
- if (host == null || host.isEmpty()) {
- return loopbackAddresses();
- }
-
- // Is it a numeric address?
- InetAddress result = parseNumericAddressNoThrow(host);
- if (result != null) {
- result = disallowDeprecatedFormats(host, result);
- if (result == null) {
- throw new UnknownHostException("Deprecated IPv4 address format: " + host);
- }
- return new InetAddress[] { result };
- }
-
- return lookupHostByName(host, netId).clone();
+ // Only called by java.net.SocketPermission.
+ static InetAddress[] getAllByName0(String authHost, boolean check) throws UnknownHostException {
+ throw new UnsupportedOperationException();
}
- /**
- * Resolves a hostname to its IP addresses using a cache.
- *
- * @param host the hostname to resolve.
- * @param netId the network to perform resolution upon.
- * @return the IP addresses of the host.
- */
- private static InetAddress[] lookupHostByName(String host, int netId)
- throws UnknownHostException {
- BlockGuard.getThreadPolicy().onNetwork();
- // Do we have a result cached?
- Object cachedResult = addressCache.get(host, netId);
- if (cachedResult != null) {
- if (cachedResult instanceof InetAddress[]) {
- // A cached positive result.
- return (InetAddress[]) cachedResult;
- } else {
- // A cached negative result.
- throw new UnknownHostException((String) cachedResult);
- }
- }
- try {
- StructAddrinfo hints = new StructAddrinfo();
- hints.ai_flags = AI_ADDRCONFIG;
- hints.ai_family = AF_UNSPEC;
- // If we don't specify a socket type, every address will appear twice, once
- // for SOCK_STREAM and one for SOCK_DGRAM. Since we do not return the family
- // anyway, just pick one.
- hints.ai_socktype = SOCK_STREAM;
- InetAddress[] addresses = Libcore.os.android_getaddrinfo(host, hints, netId);
- // TODO: should getaddrinfo set the hostname of the InetAddresses it returns?
- for (InetAddress address : addresses) {
- address.holder().hostName = host;
- }
- addressCache.put(host, netId, addresses);
- return addresses;
- } catch (GaiException gaiException) {
- // If the failure appears to have been a lack of INTERNET permission, throw a clear
- // SecurityException to aid in debugging this common mistake.
- // http://code.google.com/p/android/issues/detail?id=15722
- if (gaiException.getCause() instanceof ErrnoException) {
- if (((ErrnoException) gaiException.getCause()).errno == EACCES) {
- throw new SecurityException("Permission denied (missing INTERNET permission?)", gaiException);
- }
- }
- // Otherwise, throw an UnknownHostException.
- String detailMessage = "Unable to resolve host \"" + host + "\": " + Libcore.os.gai_strerror(gaiException.error);
- addressCache.putUnknownHost(host, netId, detailMessage);
- throw gaiException.rethrowAsUnknownHostException(detailMessage);
- }
+ // Only called by java.net.SocketPermission.
+ String getHostName(boolean check) {
+ throw new UnsupportedOperationException();
}
-
- private static InetAddress[] loopbackAddresses() {
- return new InetAddress[] { Inet6Address.LOOPBACK, Inet4Address.LOOPBACK };
- }
-}
-
-/*
- * Simple factory to create the impl
- */
-class InetAddressImplFactory {
-
- static InetAddressImpl create() {
- return InetAddress.loadImpl("Inet6AddressImpl");
- }
-}
+}
\ No newline at end of file
diff --git a/ojluni/src/main/java/java/net/InetAddressImpl.java b/ojluni/src/main/java/java/net/InetAddressImpl.java
index bb67962..e5821a3 100755
--- a/ojluni/src/main/java/java/net/InetAddressImpl.java
+++ b/ojluni/src/main/java/java/net/InetAddressImpl.java
@@ -35,14 +35,34 @@
* @since 1.4
*/
interface InetAddressImpl {
+ /**
+ * Lookup all addresses for {@code hostname} on the given {@code netId}.
+ */
+ InetAddress[] lookupAllHostAddr(String hostname, int netId) throws UnknownHostException;
- String getLocalHostName() throws UnknownHostException;
- InetAddress[]
- lookupAllHostAddr(String hostname) throws UnknownHostException;
+ /**
+ * Reverse-lookup the host name for a given {@code addr}.
+ */
String getHostByAddr(byte[] addr) throws UnknownHostException;
+ /**
+ * Clear address caches (if any).
+ */
+ public void clearAddressCache();
+
+ /**
+ * Return the "any" local address.
+ */
InetAddress anyLocalAddress();
- InetAddress loopbackAddress();
+
+ /**
+ * Return a list of loop back adresses for this implementation.
+ */
+ InetAddress[] loopbackAddresses();
+
+ /**
+ * Whether {@code addr} is reachable over {@code netif}.
+ */
boolean isReachable(InetAddress addr, int timeout, NetworkInterface netif,
int ttl) throws IOException;
}
diff --git a/ojluni/src/main/java/java/net/SocketInputStream.java b/ojluni/src/main/java/java/net/SocketInputStream.java
index dda7a4a..3892b5b 100755
--- a/ojluni/src/main/java/java/net/SocketInputStream.java
+++ b/ojluni/src/main/java/java/net/SocketInputStream.java
@@ -31,6 +31,7 @@
import java.io.IOException;
import java.nio.channels.FileChannel;
+import dalvik.system.BlockGuard;
import sun.misc.IoTrace;
import sun.net.ConnectionResetException;
@@ -150,6 +151,7 @@
// acquire file descriptor and do the read
FileDescriptor fd = impl.acquireFD();
try {
+ BlockGuard.getThreadPolicy().onNetwork();
n = socketRead0(fd, b, off, length, timeout);
if (n > 0) {
return n;
@@ -214,7 +216,7 @@
/**
* Skips n bytes of input.
- * @param n the number of bytes to skip
+ * @param numbytes the number of bytes to skip
* @return the actual number of bytes skipped.
* @exception IOException If an I/O error has occurred.
*/
diff --git a/ojluni/src/main/java/java/net/SocketOutputStream.java b/ojluni/src/main/java/java/net/SocketOutputStream.java
index e351035..36d0da7 100755
--- a/ojluni/src/main/java/java/net/SocketOutputStream.java
+++ b/ojluni/src/main/java/java/net/SocketOutputStream.java
@@ -31,6 +31,7 @@
import java.io.IOException;
import java.nio.channels.FileChannel;
+import dalvik.system.BlockGuard;
import sun.misc.IoTrace;
/**
@@ -111,6 +112,7 @@
int bytesWritten = 0;
FileDescriptor fd = impl.acquireFD();
try {
+ BlockGuard.getThreadPolicy().onNetwork();
socketWrite0(fd, b, off, len);
bytesWritten = len;
} catch (SocketException se) {
diff --git a/ojluni/src/main/java/java/net/URI.java b/ojluni/src/main/java/java/net/URI.java
index 82b8cb6..6048994 100755
--- a/ojluni/src/main/java/java/net/URI.java
+++ b/ojluni/src/main/java/java/net/URI.java
@@ -3387,7 +3387,19 @@
do {
// domainlabel = alphanum [ *( alphanum | "-" | "_" ) alphanum ]
- //
+
+ // RFC1034#section-3.5 doesn't permit empty labels in hostnames, but we accepted
+ // this prior to N and the behavior is used by some apps. They're accepted for
+ // compatibility but we produce a warning in the log.
+ // http://b/25991669
+ if (charAt(p) == '.') {
+ java.lang.System.logE("URI " + substring(start, n) + " has empty labels in " +
+ "the hostname. This is malformed and will not be accepted" +
+ "in future Android releases.");
+ q = ++p;
+ continue;
+ }
+
// The RFCs don't permit underscores in hostnames, but URI has to because a certain
// large website doesn't seem to care about standards and specs.
// http://code.google.com/p/android/issues/detail?id=37577
diff --git a/ojluni/src/main/java/java/nio/charset/Charset.java b/ojluni/src/main/java/java/nio/charset/Charset.java
index 1313828..a6ca2d7 100755
--- a/ojluni/src/main/java/java/nio/charset/Charset.java
+++ b/ojluni/src/main/java/java/nio/charset/Charset.java
@@ -34,7 +34,9 @@
import java.security.AccessController;
import java.security.AccessControlException;
import java.security.PrivilegedAction;
+import java.util.AbstractMap;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
@@ -330,12 +332,30 @@
// Cache of the most-recently-returned charsets,
// along with the names that were used to find them
//
- private static volatile Object[] cache1 = null; // "Level 1" cache
- private static volatile Object[] cache2 = null; // "Level 2" cache
+ // cache1/2 usage is explained in the lookup method
+ //
+ private static volatile Map.Entry<String, Charset> cache1 = null; // "Level 1" cache
+ private static final HashMap<String, Charset> cache2 = new HashMap<>(); // "Level 2" cache
private static void cache(String charsetName, Charset cs) {
- cache2 = cache1;
- cache1 = new Object[] { charsetName, cs };
+ synchronized(cache2) {
+ String canonicalName = cs.name();
+ Charset canonicalCharset = cache2.get(canonicalName);
+
+ if (canonicalCharset != null) {
+ cs = canonicalCharset;
+ } else {
+ cache2.put(canonicalName, cs);
+
+ for (String alias : cs.aliases()) {
+ cache2.put(alias, cs);
+ }
+ }
+
+ cache2.put(charsetName, cs);
+ }
+
+ cache1 = new AbstractMap.SimpleImmutableEntry<>(charsetName, cs);
}
// Creates an iterator that walks over the available providers, ignoring
@@ -466,28 +486,29 @@
// return (ecp != null) ? ecp.charsetForName(charsetName) : null;
// }
+ // We expect most programs to use one Charset repeatedly, so the most recently used Charset
+ // instance is stored in the level 1 cache. We convey a hint to this effect to the VM by putting
+ // the level 1 cache miss code in a separate method. Since charsetName is not necessarily in
+ // canonical form, we store the mapping from both the canonical name and the aliases to the
+ // instance in a map for level 2 cache.
private static Charset lookup(String charsetName) {
if (charsetName == null)
throw new IllegalArgumentException("Null charset name");
- Object[] a;
- if ((a = cache1) != null && charsetName.equals(a[0]))
- return (Charset)a[1];
- // We expect most programs to use one Charset repeatedly.
- // We convey a hint to this effect to the VM by putting the
- // level 1 cache miss code in a separate method.
+ if (cache1 != null && charsetName.equals(cache1.getKey()))
+ return cache1.getValue();
return lookup2(charsetName);
}
private static Charset lookup2(String charsetName) {
- Object[] a;
- if ((a = cache2) != null && charsetName.equals(a[0])) {
- cache2 = cache1;
- cache1 = a;
- return (Charset)a[1];
+ Charset cs;
+ synchronized (cache2) {
+ if ((cs = cache2.get(charsetName)) != null) {
+ cache1 = new AbstractMap.SimpleImmutableEntry<>(charsetName, cs);
+ return cs;
+ }
}
- Charset cs;
// Android-changed: Drop support for "standard" and "extended"
// providers.
if ((cs = NativeConverter.charsetForName(charsetName)) != null ||
diff --git a/ojluni/src/main/java/java/util/Locale.java b/ojluni/src/main/java/java/util/Locale.java
index 6762d48..21576b7 100755
--- a/ojluni/src/main/java/java/util/Locale.java
+++ b/ojluni/src/main/java/java/util/Locale.java
@@ -2083,7 +2083,7 @@
String variant = (String)fields.get("variant", "");
String extStr = (String)fields.get("extensions", "");
baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), script, country, variant);
- if (extStr.length() > 0) {
+ if (extStr != null && extStr.length() > 0) {
try {
InternalLocaleBuilder bldr = new InternalLocaleBuilder();
bldr.setExtensions(extStr);
diff --git a/ojluni/src/main/java/java/util/zip/Deflater.java b/ojluni/src/main/java/java/util/zip/Deflater.java
index e5e9b27..f05c27a 100755
--- a/ojluni/src/main/java/java/util/zip/Deflater.java
+++ b/ojluni/src/main/java/java/util/zip/Deflater.java
@@ -25,6 +25,8 @@
package java.util.zip;
+import dalvik.system.CloseGuard;
+
/**
* This class provides support for general purpose compression using the
* popular ZLIB compression library. The ZLIB compression library was
@@ -82,6 +84,8 @@
private long bytesRead;
private long bytesWritten;
+ private final CloseGuard guard = CloseGuard.get();
+
/**
* Compression method for the deflate algorithm (the only one currently
* supported).
@@ -169,6 +173,7 @@
this.level = level;
this.strategy = DEFAULT_STRATEGY;
this.zsRef = new ZStreamRef(init(level, DEFAULT_STRATEGY, nowrap));
+ guard.open("end");
}
/**
@@ -523,6 +528,8 @@
*/
public void end() {
synchronized (zsRef) {
+ guard.close();
+
long addr = zsRef.address();
zsRef.clear();
if (addr != 0) {
@@ -536,6 +543,10 @@
* Closes the compressor when garbage is collected.
*/
protected void finalize() {
+ if (guard != null) {
+ guard.warnIfOpen();
+ }
+
end();
}
diff --git a/ojluni/src/main/java/java/util/zip/Inflater.java b/ojluni/src/main/java/java/util/zip/Inflater.java
index d7a16f9..a2ab9cb 100755
--- a/ojluni/src/main/java/java/util/zip/Inflater.java
+++ b/ojluni/src/main/java/java/util/zip/Inflater.java
@@ -26,6 +26,8 @@
package java.util.zip;
+import dalvik.system.CloseGuard;
+
/**
* This class provides support for general purpose decompression using the
* popular ZLIB compression library. The ZLIB compression library was
@@ -82,6 +84,8 @@
private long bytesRead;
private long bytesWritten;
+ private final CloseGuard guard = CloseGuard.get();
+
private static final byte[] defaultBuf = new byte[0];
static {
@@ -102,6 +106,7 @@
*/
public Inflater(boolean nowrap) {
zsRef = new ZStreamRef(init(nowrap));
+ guard.open("end");
}
/**
@@ -368,6 +373,8 @@
*/
public void end() {
synchronized (zsRef) {
+ guard.close();
+
long addr = zsRef.address();
zsRef.clear();
if (addr != 0) {
@@ -381,6 +388,10 @@
* Closes the decompressor when garbage is collected.
*/
protected void finalize() {
+ if (guard != null) {
+ guard.warnIfOpen();
+ }
+
end();
}
diff --git a/ojluni/src/main/java/java/util/zip/ZipFile.java b/ojluni/src/main/java/java/util/zip/ZipFile.java
index 2e15c7c..f9e7268 100755
--- a/ojluni/src/main/java/java/util/zip/ZipFile.java
+++ b/ojluni/src/main/java/java/util/zip/ZipFile.java
@@ -43,6 +43,8 @@
import java.util.Set;
import java.util.WeakHashMap;
import java.security.AccessController;
+
+import dalvik.system.CloseGuard;
import sun.security.action.GetPropertyAction;
import static java.util.zip.ZipConstants64.*;
@@ -64,6 +66,8 @@
private final boolean locsig; // if zip file starts with LOCSIG (usually true)
private volatile boolean closeRequested = false;
+ private final CloseGuard guard = CloseGuard.get();
+
private static final int STORED = ZipEntry.STORED;
private static final int DEFLATED = ZipEntry.DEFLATED;
@@ -217,7 +221,6 @@
if (charset == null)
throw new NullPointerException("charset is null");
this.zc = ZipCoder.get(charset);
- long t0 = System.nanoTime();
jzfile = open(name, mode, file.lastModified(), usemmap);
this.name = name;
this.total = getTotal(jzfile);
@@ -245,6 +248,8 @@
}
entryNames.add(entryName);
}
+
+ guard.open("close");
}
/**
@@ -600,6 +605,7 @@
public void close() throws IOException {
if (closeRequested)
return;
+ guard.close();
closeRequested = true;
synchronized (this) {
@@ -651,6 +657,10 @@
* @see java.util.zip.ZipFile#close()
*/
protected void finalize() throws IOException {
+ if (guard != null) {
+ guard.warnIfOpen();
+ }
+
close();
}
diff --git a/ojluni/src/main/java/sun/net/spi/nameservice/NameService.java b/ojluni/src/main/java/sun/net/spi/nameservice/NameService.java
index 902ea87..6fbd4ff 100755
--- a/ojluni/src/main/java/sun/net/spi/nameservice/NameService.java
+++ b/ojluni/src/main/java/sun/net/spi/nameservice/NameService.java
@@ -28,6 +28,6 @@
import java.net.UnknownHostException;
public interface NameService {
- public java.net.InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException;
+ public java.net.InetAddress[] lookupAllHostAddr(String host, int netId) throws UnknownHostException;
public String getHostByAddr(byte[] addr) throws UnknownHostException;
}
diff --git a/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java
index d737276..9715df8 100755
--- a/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java
@@ -33,6 +33,8 @@
import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.util.*;
+
+import dalvik.system.BlockGuard;
import sun.net.ResourceManager;
@@ -413,6 +415,8 @@
int newSize = Math.max(rem, 1);
ByteBuffer bb = Util.getTemporaryDirectBuffer(newSize);
try {
+ BlockGuard.getThreadPolicy().onNetwork();
+
int n = receiveIntoNativeBuffer(fd, bb, newSize, 0);
bb.flip();
if (n > 0 && rem > 0)
@@ -474,6 +478,8 @@
if (!isOpen())
return 0;
writerThread = NativeThread.current();
+ BlockGuard.getThreadPolicy().onNetwork();
+
do {
n = send(fd, src, isa);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
diff --git a/ojluni/src/main/java/sun/nio/ch/DatagramDispatcher.java b/ojluni/src/main/java/sun/nio/ch/DatagramDispatcher.java
index 64d4c31..a576062 100755
--- a/ojluni/src/main/java/sun/nio/ch/DatagramDispatcher.java
+++ b/ojluni/src/main/java/sun/nio/ch/DatagramDispatcher.java
@@ -25,6 +25,8 @@
package sun.nio.ch;
+import dalvik.system.BlockGuard;
+
import java.io.*;
import java.net.*;
@@ -40,18 +42,22 @@
}
int read(FileDescriptor fd, long address, int len) throws IOException {
+ BlockGuard.getThreadPolicy().onNetwork();
return read0(fd, address, len);
}
long readv(FileDescriptor fd, long address, int len) throws IOException {
+ BlockGuard.getThreadPolicy().onNetwork();
return readv0(fd, address, len);
}
int write(FileDescriptor fd, long address, int len) throws IOException {
+ BlockGuard.getThreadPolicy().onNetwork();
return write0(fd, address, len);
}
long writev(FileDescriptor fd, long address, int len) throws IOException {
+ BlockGuard.getThreadPolicy().onNetwork();
return writev0(fd, address, len);
}
diff --git a/ojluni/src/main/java/sun/nio/ch/FileChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/FileChannelImpl.java
index e4de807..3e0e630 100755
--- a/ojluni/src/main/java/sun/nio/ch/FileChannelImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/FileChannelImpl.java
@@ -35,6 +35,8 @@
import java.util.ArrayList;
import java.util.List;
import java.security.AccessController;
+
+import dalvik.system.BlockGuard;
import sun.misc.Cleaner;
import sun.misc.IoTrace;
import sun.security.action.GetPropertyAction;
@@ -264,6 +266,9 @@
ti = threads.add();
if (!isOpen())
return 0;
+ if (append) {
+ BlockGuard.getThreadPolicy().onWriteToDisk();
+ }
do {
// in append-mode then position is advanced to end before writing
p = (append) ? nd.size(fd) : position0(fd, -1);
@@ -289,6 +294,7 @@
ti = threads.add();
if (!isOpen())
return null;
+ BlockGuard.getThreadPolicy().onReadFromDisk();
do {
p = position0(fd, newPosition);
} while ((p == IOStatus.INTERRUPTED) && isOpen());
@@ -445,6 +451,7 @@
ti = threads.add();
if (!isOpen())
return -1;
+ BlockGuard.getThreadPolicy().onWriteToDisk();
do {
n = transferTo0(thisFDVal, position, icount, targetFDVal);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
@@ -905,6 +912,7 @@
long mapSize = size + pagePosition;
try {
// If no exception was thrown from map0, the address is valid
+ BlockGuard.getThreadPolicy().onReadFromDisk();
addr = map0(imode, mapPosition, mapSize);
} catch (OutOfMemoryError x) {
// An OutOfMemoryError may indicate that we've exhausted memory
diff --git a/ojluni/src/main/java/sun/nio/ch/FileDispatcherImpl.java b/ojluni/src/main/java/sun/nio/ch/FileDispatcherImpl.java
index 8fcfae6..e57ccc5 100755
--- a/ojluni/src/main/java/sun/nio/ch/FileDispatcherImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/FileDispatcherImpl.java
@@ -25,6 +25,8 @@
package sun.nio.ch;
+import dalvik.system.BlockGuard;
+
import java.io.*;
class FileDispatcherImpl extends FileDispatcher
@@ -42,54 +44,65 @@
}
int read(FileDescriptor fd, long address, int len) throws IOException {
+ BlockGuard.getThreadPolicy().onReadFromDisk();
return read0(fd, address, len);
}
int pread(FileDescriptor fd, long address, int len, long position)
throws IOException
{
+ BlockGuard.getThreadPolicy().onReadFromDisk();
return pread0(fd, address, len, position);
}
long readv(FileDescriptor fd, long address, int len) throws IOException {
+ BlockGuard.getThreadPolicy().onReadFromDisk();
return readv0(fd, address, len);
}
int write(FileDescriptor fd, long address, int len) throws IOException {
+ BlockGuard.getThreadPolicy().onWriteToDisk();
return write0(fd, address, len);
}
int pwrite(FileDescriptor fd, long address, int len, long position)
throws IOException
{
+ BlockGuard.getThreadPolicy().onWriteToDisk();
return pwrite0(fd, address, len, position);
}
long writev(FileDescriptor fd, long address, int len)
throws IOException
{
+ BlockGuard.getThreadPolicy().onWriteToDisk();
return writev0(fd, address, len);
}
int force(FileDescriptor fd, boolean metaData) throws IOException {
+ BlockGuard.getThreadPolicy().onWriteToDisk();
return force0(fd, metaData);
}
int truncate(FileDescriptor fd, long size) throws IOException {
+ BlockGuard.getThreadPolicy().onWriteToDisk();
return truncate0(fd, size);
}
long size(FileDescriptor fd) throws IOException {
+ BlockGuard.getThreadPolicy().onReadFromDisk();
return size0(fd);
}
int lock(FileDescriptor fd, boolean blocking, long pos, long size,
boolean shared) throws IOException
{
+ BlockGuard.getThreadPolicy().onWriteToDisk();
return lock0(fd, blocking, pos, size, shared);
}
void release(FileDescriptor fd, long pos, long size) throws IOException {
+ BlockGuard.getThreadPolicy().onWriteToDisk();
release0(fd, pos, size);
}
diff --git a/ojluni/src/main/java/sun/nio/ch/Net.java b/ojluni/src/main/java/sun/nio/ch/Net.java
index a3a519a..104e9af 100755
--- a/ojluni/src/main/java/sun/nio/ch/Net.java
+++ b/ojluni/src/main/java/sun/nio/ch/Net.java
@@ -26,6 +26,8 @@
package sun.nio.ch;
+import dalvik.system.BlockGuard;
+
import java.io.*;
import java.net.*;
import java.nio.channels.*;
@@ -468,6 +470,8 @@
static int connect(ProtocolFamily family, FileDescriptor fd, InetAddress remote, int remotePort)
throws IOException
{
+ BlockGuard.getThreadPolicy().onNetwork();
+
boolean preferIPv6 = isIPv6Available() &&
(family != StandardProtocolFamily.INET);
return connect0(preferIPv6, fd, remote, remotePort);
diff --git a/ojluni/src/main/java/sun/nio/ch/SocketChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/SocketChannelImpl.java
index d3b5580..b72b68f 100755
--- a/ojluni/src/main/java/sun/nio/ch/SocketChannelImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/SocketChannelImpl.java
@@ -33,6 +33,8 @@
import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.util.*;
+
+import dalvik.system.BlockGuard;
import sun.net.NetHooks;
import sun.misc.IoTrace;
@@ -733,6 +735,8 @@
}
readerThread = NativeThread.current();
}
+
+ BlockGuard.getThreadPolicy().onNetwork();
if (!isBlocking()) {
for (;;) {
n = checkConnect(fd, false,
diff --git a/ojluni/src/main/java/sun/nio/ch/SocketDispatcher.java b/ojluni/src/main/java/sun/nio/ch/SocketDispatcher.java
index 1c5f8ef..8dde1f9 100755
--- a/ojluni/src/main/java/sun/nio/ch/SocketDispatcher.java
+++ b/ojluni/src/main/java/sun/nio/ch/SocketDispatcher.java
@@ -25,6 +25,8 @@
package sun.nio.ch;
+import dalvik.system.BlockGuard;
+
import java.io.*;
/**
@@ -36,18 +38,22 @@
{
int read(FileDescriptor fd, long address, int len) throws IOException {
+ BlockGuard.getThreadPolicy().onNetwork();
return FileDispatcherImpl.read0(fd, address, len);
}
long readv(FileDescriptor fd, long address, int len) throws IOException {
+ BlockGuard.getThreadPolicy().onNetwork();
return FileDispatcherImpl.readv0(fd, address, len);
}
int write(FileDescriptor fd, long address, int len) throws IOException {
+ BlockGuard.getThreadPolicy().onNetwork();
return FileDispatcherImpl.write0(fd, address, len);
}
long writev(FileDescriptor fd, long address, int len) throws IOException {
+ BlockGuard.getThreadPolicy().onNetwork();
return FileDispatcherImpl.writev0(fd, address, len);
}
diff --git a/ojluni/src/main/native/Inet6AddressImpl.c b/ojluni/src/main/native/Inet6AddressImpl.c
index d3b8699..e0ad5d3 100755
--- a/ojluni/src/main/native/Inet6AddressImpl.c
+++ b/ojluni/src/main/native/Inet6AddressImpl.c
@@ -60,66 +60,6 @@
* Inet6AddressImpl
*/
-/*
- * Class: java_net_Inet6AddressImpl
- * Method: getLocalHostName
- * Signature: ()Ljava/lang/String;
- */
-JNIEXPORT jstring JNICALL
-Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
- char hostname[NI_MAXHOST+1];
-
- hostname[0] = '\0';
- if (JVM_GetHostName(hostname, sizeof(hostname))) {
- /* Something went wrong, maybe networking is not setup? */
- strcpy(hostname, "localhost");
- } else {
- // ensure null-terminated
- hostname[NI_MAXHOST] = '\0';
-#if defined(__linux__) || defined(_ALLBSD_SOURCE)
- /* On Linux/FreeBSD gethostname() says "host.domain.sun.com". On
- * Solaris gethostname() says "host", so extra work is needed.
- */
-#else
- /* Solaris doesn't want to give us a fully qualified domain name.
- * We do a reverse lookup to try and get one. This works
- * if DNS occurs before NIS in /etc/resolv.conf, but fails
- * if NIS comes first (it still gets only a partial name).
- * We use thread-safe system calls.
- */
-#ifdef AF_INET6
- if (NET_addrtransAvailable()) {
- struct addrinfo hints, *res;
- int error;
-
- bzero(&hints, sizeof(hints));
- hints.ai_flags = AI_CANONNAME;
- hints.ai_family = AF_UNSPEC;
-
- error = (*getaddrinfo_ptr)(hostname, NULL, &hints, &res);
-
- if (error == 0) {
- /* host is known to name service */
- error = (*getnameinfo_ptr)(res->ai_addr,
- res->ai_addrlen,
- hostname,
- NI_MAXHOST,
- NULL,
- 0,
- NI_NAMEREQD);
-
- /* if getnameinfo fails hostname is still the value
- from gethostname */
-
- (*freeaddrinfo_ptr)(res);
- }
- }
-#endif /* AF_INET6 */
-#endif /* __linux__ || _ALLBSD_SOURCE */
- }
- return (*env)->NewStringUTF(env, hostname);
-}
-
static jclass ni_iacls;
static jclass ni_ia4cls;
static jclass ni_ia6cls;
@@ -129,260 +69,13 @@
static int initialized = 0;
/*
- * Find an internet address for a given hostname. Note that this
- * code only works for addresses of type INET. The translation
- * of %d.%d.%d.%d to an address (int) occurs in java now, so the
- * String "host" shouldn't *ever* be a %d.%d.%d.%d string
- *
- * Class: java_net_Inet6AddressImpl
- * Method: lookupAllHostAddr
- * Signature: (Ljava/lang/String;)[[B
- */
-
-JNIEXPORT jobjectArray JNICALL
-Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
- jstring host) {
- const char *hostname;
- jobjectArray ret = 0;
- int retLen = 0;
- jboolean preferIPv6Address;
-
- int error=0;
-#ifdef AF_INET6
- struct addrinfo hints, *res, *resNew = NULL;
-#endif /* AF_INET6 */
-
- if (!initialized) {
- ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
- ni_iacls = (*env)->NewGlobalRef(env, ni_iacls);
- ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address");
- ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls);
- ni_ia6cls = (*env)->FindClass(env, "java/net/Inet6Address");
- ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls);
- ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
- ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V");
- ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B");
- initialized = 1;
- }
-
- if (IS_NULL(host)) {
- JNU_ThrowNullPointerException(env, "host is null");
- return 0;
- }
- hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
- CHECK_NULL_RETURN(hostname, NULL);
-
-#ifdef AF_INET6
- if (NET_addrtransAvailable()) {
- static jfieldID ia_preferIPv6AddressID;
- if (ia_preferIPv6AddressID == NULL) {
- jclass c = (*env)->FindClass(env,"java/net/InetAddress");
- if (c) {
- ia_preferIPv6AddressID =
- (*env)->GetStaticFieldID(env, c, "preferIPv6Address", "Z");
- }
- if (ia_preferIPv6AddressID == NULL) {
- JNU_ReleaseStringPlatformChars(env, host, hostname);
- return NULL;
- }
- }
- /* get the address preference */
- preferIPv6Address
- = (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID);
-
- /* Try once, with our static buffer. */
- bzero(&hints, sizeof(hints));
- hints.ai_flags = AI_CANONNAME;
- hints.ai_family = AF_UNSPEC;
-
-#ifdef __solaris__
- /*
- * Workaround for Solaris bug 4160367 - if a hostname contains a
- * white space then 0.0.0.0 is returned
- */
- if (isspace((unsigned char)hostname[0])) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
- hostname);
- JNU_ReleaseStringPlatformChars(env, host, hostname);
- return NULL;
- }
-#endif
-
- error = (*getaddrinfo_ptr)(hostname, NULL, &hints, &res);
-
- if (error) {
- /* report error */
- ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
- JNU_ReleaseStringPlatformChars(env, host, hostname);
- return NULL;
- } else {
- int i = 0;
- int inetCount = 0, inet6Count = 0, inetIndex, inet6Index;
- struct addrinfo *itr, *last = NULL, *iterator = res;
- while (iterator != NULL) {
- int skip = 0;
- itr = resNew;
- while (itr != NULL) {
- if (iterator->ai_family == itr->ai_family &&
- iterator->ai_addrlen == itr->ai_addrlen) {
- if (itr->ai_family == AF_INET) { /* AF_INET */
- struct sockaddr_in *addr1, *addr2;
- addr1 = (struct sockaddr_in *)iterator->ai_addr;
- addr2 = (struct sockaddr_in *)itr->ai_addr;
- if (addr1->sin_addr.s_addr ==
- addr2->sin_addr.s_addr) {
- skip = 1;
- break;
- }
- } else {
- int t;
- struct sockaddr_in6 *addr1, *addr2;
- addr1 = (struct sockaddr_in6 *)iterator->ai_addr;
- addr2 = (struct sockaddr_in6 *)itr->ai_addr;
-
- for (t = 0; t < 16; t++) {
- if (addr1->sin6_addr.s6_addr[t] !=
- addr2->sin6_addr.s6_addr[t]) {
- break;
- }
- }
- if (t < 16) {
- itr = itr->ai_next;
- continue;
- } else {
- skip = 1;
- break;
- }
- }
- } else if (iterator->ai_family != AF_INET &&
- iterator->ai_family != AF_INET6) {
- /* we can't handle other family types */
- skip = 1;
- break;
- }
- itr = itr->ai_next;
- }
-
- if (!skip) {
- struct addrinfo *next
- = (struct addrinfo*) malloc(sizeof(struct addrinfo));
- if (!next) {
- JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
- ret = NULL;
- goto cleanupAndReturn;
- }
- memcpy(next, iterator, sizeof(struct addrinfo));
- next->ai_next = NULL;
- if (resNew == NULL) {
- resNew = next;
- } else {
- last->ai_next = next;
- }
- last = next;
- i++;
- if (iterator->ai_family == AF_INET) {
- inetCount ++;
- } else if (iterator->ai_family == AF_INET6) {
- inet6Count ++;
- }
- }
- iterator = iterator->ai_next;
- }
- retLen = i;
- iterator = resNew;
-
- ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL);
-
- if (IS_NULL(ret)) {
- /* we may have memory to free at the end of this */
- goto cleanupAndReturn;
- }
-
- if (preferIPv6Address) {
- /* AF_INET addresses will be offset by inet6Count */
- inetIndex = inet6Count;
- inet6Index = 0;
- } else {
- /* AF_INET6 addresses will be offset by inetCount */
- inetIndex = 0;
- inet6Index = inetCount;
- }
-
- while (iterator != NULL) {
- if (iterator->ai_family == AF_INET) {
- jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
- if (IS_NULL(iaObj)) {
- ret = NULL;
- goto cleanupAndReturn;
- }
- setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
- setInetAddress_hostName(env, iaObj, host);
- (*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
- inetIndex++;
- } else if (iterator->ai_family == AF_INET6) {
- jint scope = 0;
- jbyteArray ipaddress;
-
- jobject iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
- if (IS_NULL(iaObj)) {
- ret = NULL;
- goto cleanupAndReturn;
- }
- ipaddress = (*env)->NewByteArray(env, 16);
- if (IS_NULL(ipaddress)) {
- ret = NULL;
- goto cleanupAndReturn;
- }
- (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
- (jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
-#ifdef __linux__
- if (!kernelIsV22()) {
- scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
- }
-#else
- scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
-#endif
- if (scope != 0) { /* zero is default value, no need to set */
- (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
- (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
- }
- (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
- setInetAddress_hostName(env, iaObj, host);
- (*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
- inet6Index++;
- }
- iterator = iterator->ai_next;
- }
- }
- }
-
-cleanupAndReturn:
- {
- struct addrinfo *iterator, *tmp;
- iterator = resNew;
- while (iterator != NULL) {
- tmp = iterator;
- iterator = iterator->ai_next;
- free(tmp);
- }
- JNU_ReleaseStringPlatformChars(env, host, hostname);
- }
-
- if (NET_addrtransAvailable())
- (*freeaddrinfo_ptr)(res);
-#endif /* AF_INET6 */
-
- return ret;
-}
-
-/*
* Class: java_net_Inet6AddressImpl
* Method: getHostByAddr
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
-Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
- jbyteArray addrArray) {
+Inet6AddressImpl_getHostByAddr0(JNIEnv *env, jobject this,
+ jbyteArray addrArray) {
jstring ret = NULL;
@@ -723,9 +416,7 @@
static JNINativeMethod gMethods[] = {
NATIVE_METHOD(Inet6AddressImpl, isReachable0, "([BII[BII)Z"),
- NATIVE_METHOD(Inet6AddressImpl, getHostByAddr, "([B)Ljava/lang/String;"),
- NATIVE_METHOD(Inet6AddressImpl, getLocalHostName, "()Ljava/lang/String;"),
- NATIVE_METHOD(Inet6AddressImpl, lookupAllHostAddr, "(Ljava/lang/String;)[Ljava/net/InetAddress;"),
+ NATIVE_METHOD(Inet6AddressImpl, getHostByAddr0, "([B)Ljava/lang/String;"),
};
void register_java_net_Inet6AddressImpl(JNIEnv* env) {
diff --git a/ojluni/src/main/native/InetAddress.c b/ojluni/src/main/native/InetAddress.c
index 7fb8890..ef76ed8 100755
--- a/ojluni/src/main/native/InetAddress.c
+++ b/ojluni/src/main/native/InetAddress.c
@@ -41,7 +41,6 @@
jfieldID iac_addressID;
jfieldID iac_familyID;
jfieldID iac_hostNameID;
-jfieldID ia_preferIPv6AddressID;
/*
* Class: java_net_InetAddress
@@ -59,8 +58,6 @@
iac_class = (*env)->NewGlobalRef(env, c);
ia_holderID = (*env)->GetFieldID(env, ia_class, "holder", "Ljava/net/InetAddress$InetAddressHolder;");
CHECK_NULL(ia_holderID);
- ia_preferIPv6AddressID = (*env)->GetStaticFieldID(env, ia_class, "preferIPv6Address", "Z");
- CHECK_NULL(ia_preferIPv6AddressID);
iac_addressID = (*env)->GetFieldID(env, iac_class, "address", "I");
CHECK_NULL(iac_addressID);
diff --git a/ojluni/src/main/native/Net.c b/ojluni/src/main/native/Net.c
index 9c1c098..3bdbf4d 100644
--- a/ojluni/src/main/native/Net.c
+++ b/ojluni/src/main/native/Net.c
@@ -260,7 +260,7 @@
} else if (errno == EINTR) {
return IOS_INTERRUPTED;
}
- return handleSocketError(env, errno);
+ return handleSocketErrorWithDefault(env, errno, JNU_JAVANETPKG "ConnectException");
}
return 1;
}
@@ -655,9 +655,9 @@
/* Declared in nio_util.h */
jint
-handleSocketError(JNIEnv *env, jint errorValue)
+handleSocketErrorWithDefault(JNIEnv *env, jint errorValue, const char *defaultException)
{
- char *xn;
+ const char *xn;
switch (errorValue) {
case EINPROGRESS: /* Non-blocking connect */
return 0;
@@ -680,7 +680,7 @@
xn = JNU_JAVANETPKG "BindException";
break;
default:
- xn = JNU_JAVANETPKG "SocketException";
+ xn = defaultException;
break;
}
errno = errorValue;
@@ -688,6 +688,14 @@
return IOS_THROWN;
}
+/* Declared in nio_util.h */
+
+jint
+handleSocketError(JNIEnv *env, jint errorValue) {
+ return handleSocketErrorWithDefault(env, errorValue,
+ JNU_JAVANETPKG "SocketException");
+}
+
static JNINativeMethod gMethods[] = {
NATIVE_METHOD(Net, isIPv6Available0, "()Z"),
diff --git a/ojluni/src/main/native/UnixFileSystem_md.c b/ojluni/src/main/native/UnixFileSystem_md.c
index 578fde0..7cbb753 100755
--- a/ojluni/src/main/native/UnixFileSystem_md.c
+++ b/ojluni/src/main/native/UnixFileSystem_md.c
@@ -129,8 +129,8 @@
}
JNIEXPORT jboolean JNICALL
-Java_java_io_UnixFileSystem_checkAccess(JNIEnv *env, jobject this,
- jobject file, jint a)
+Java_java_io_UnixFileSystem_checkAccess0(JNIEnv *env, jobject this,
+ jobject file, jint a)
{
jboolean rv = JNI_FALSE;
int mode = 0;
@@ -159,11 +159,11 @@
JNIEXPORT jboolean JNICALL
-Java_java_io_UnixFileSystem_setPermission(JNIEnv *env, jobject this,
- jobject file,
- jint access,
- jboolean enable,
- jboolean owneronly)
+Java_java_io_UnixFileSystem_setPermission0(JNIEnv *env, jobject this,
+ jobject file,
+ jint access,
+ jboolean enable,
+ jboolean owneronly)
{
jboolean rv = JNI_FALSE;
@@ -206,8 +206,8 @@
}
JNIEXPORT jlong JNICALL
-Java_java_io_UnixFileSystem_getLastModifiedTime(JNIEnv *env, jobject this,
- jobject file)
+Java_java_io_UnixFileSystem_getLastModifiedTime0(JNIEnv *env, jobject this,
+ jobject file)
{
jlong rv = 0;
@@ -222,8 +222,8 @@
JNIEXPORT jlong JNICALL
-Java_java_io_UnixFileSystem_getLength(JNIEnv *env, jobject this,
- jobject file)
+Java_java_io_UnixFileSystem_getLength0(JNIEnv *env, jobject this,
+ jobject file)
{
jlong rv = 0;
@@ -241,8 +241,8 @@
JNIEXPORT jboolean JNICALL
-Java_java_io_UnixFileSystem_createFileExclusively(JNIEnv *env, jclass cls,
- jstring pathname)
+Java_java_io_UnixFileSystem_createFileExclusively0(JNIEnv *env, jclass cls,
+ jstring pathname)
{
jboolean rv = JNI_FALSE;
@@ -282,8 +282,8 @@
JNIEXPORT jobjectArray JNICALL
-Java_java_io_UnixFileSystem_list(JNIEnv *env, jobject this,
- jobject file)
+Java_java_io_UnixFileSystem_list0(JNIEnv *env, jobject this,
+ jobject file)
{
DIR *dir = NULL;
struct dirent64 *ptr;
@@ -353,8 +353,8 @@
JNIEXPORT jboolean JNICALL
-Java_java_io_UnixFileSystem_createDirectory(JNIEnv *env, jobject this,
- jobject file)
+Java_java_io_UnixFileSystem_createDirectory0(JNIEnv *env, jobject this,
+ jobject file)
{
jboolean rv = JNI_FALSE;
@@ -384,8 +384,8 @@
}
JNIEXPORT jboolean JNICALL
-Java_java_io_UnixFileSystem_setLastModifiedTime(JNIEnv *env, jobject this,
- jobject file, jlong time)
+Java_java_io_UnixFileSystem_setLastModifiedTime0(JNIEnv *env, jobject this,
+ jobject file, jlong time)
{
jboolean rv = JNI_FALSE;
@@ -413,8 +413,8 @@
JNIEXPORT jboolean JNICALL
-Java_java_io_UnixFileSystem_setReadOnly(JNIEnv *env, jobject this,
- jobject file)
+Java_java_io_UnixFileSystem_setReadOnly0(JNIEnv *env, jobject this,
+ jobject file)
{
jboolean rv = JNI_FALSE;
@@ -430,8 +430,8 @@
}
JNIEXPORT jlong JNICALL
-Java_java_io_UnixFileSystem_getSpace(JNIEnv *env, jobject this,
- jobject file, jint t)
+Java_java_io_UnixFileSystem_getSpace0(JNIEnv *env, jobject this,
+ jobject file, jint t)
{
jlong rv = 0L;
diff --git a/ojluni/src/main/native/nio_util.h b/ojluni/src/main/native/nio_util.h
index 441ea20..a0ae43f 100755
--- a/ojluni/src/main/native/nio_util.h
+++ b/ojluni/src/main/native/nio_util.h
@@ -51,3 +51,6 @@
/* Defined in Net.c */
jint handleSocketError(JNIEnv *env, jint errorValue);
+
+jint handleSocketErrorWithDefault(JNIEnv *env, jint errorValue,
+ const char *defaultException);