mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-15 21:48:57 +00:00
Merge
This commit is contained in:
commit
428cdf9465
@ -351,3 +351,4 @@ eee1ced1d8e78293f2a004af818ca474387dbebf jdk-9+103
|
||||
6e9ecae50b4e0d37483fb2719202eea5dca026a4 jdk-9+106
|
||||
8701b2bb1d2e1b9abc2a9be0933993c7150a9dbe jdk-9+107
|
||||
42794e648cfe9fd67461dcbe8b7594241a84bcff jdk-9+108
|
||||
1c7bad0798900fe58f4db01ae7ffdc84f5baee8c jdk-9+109
|
||||
|
||||
@ -29,6 +29,7 @@ include LibCommon.gmk
|
||||
$(eval $(call FillCacheFind, $(wildcard $(JDK_TOPDIR)/src/java.desktop/*/native \
|
||||
$(JDK_TOPDIR)/src/*/java.desktop/*/native)))
|
||||
|
||||
include LibosxLibraries.gmk
|
||||
include PlatformLibraries.gmk
|
||||
include Awt2dLibraries.gmk
|
||||
include SoundLibraries.gmk
|
||||
|
||||
@ -23,18 +23,15 @@
|
||||
# questions.
|
||||
#
|
||||
|
||||
include LibCommon.gmk
|
||||
|
||||
ifeq ($(OPENJDK_TARGET_OS), macosx)
|
||||
|
||||
################################################################################
|
||||
|
||||
LIBOSX_DIRS := $(JDK_TOPDIR)/src/jdk.deploy.osx/macosx/native/libosx
|
||||
LIBOSX_DIRS := $(JDK_TOPDIR)/src/java.desktop/macosx/native/libosx
|
||||
LIBOSX_CFLAGS := -I$(LIBOSX_DIRS) \
|
||||
-I$(JDK_TOPDIR)/src/java.desktop/macosx/native/libosxapp \
|
||||
$(LIBJAVA_HEADER_FLAGS) \
|
||||
-I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \
|
||||
-I$(SUPPORT_OUTPUTDIR)/headers/jdk.deploy.osx \
|
||||
#
|
||||
|
||||
$(eval $(call SetupNativeCompilation,BUILD_LIBOSX, \
|
||||
@ -1,45 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
# ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
#
|
||||
|
||||
# Define library interface.
|
||||
|
||||
SUNWprivate_1.1 {
|
||||
global:
|
||||
Java_oracle_jrockit_jfr_Process_getpid;
|
||||
Java_oracle_jrockit_jfr_Timing_counterTime;
|
||||
Java_oracle_jrockit_jfr_Timing_init;
|
||||
Java_oracle_jrockit_jfr_Logger_output0;
|
||||
Java_oracle_jrockit_jfr_JFR_isCommercialFeaturesUnlocked;
|
||||
Java_oracle_jrockit_jfr_JFR_isStarted;
|
||||
Java_oracle_jrockit_jfr_JFR_isSupportedInVM;
|
||||
Java_oracle_jrockit_jfr_JFR_startFlightRecorder;
|
||||
Java_oracle_jrockit_jfr_JFR_isDisabledOnCommandLine;
|
||||
Java_oracle_jrockit_jfr_JFR_isEnabled;
|
||||
Java_oracle_jrockit_jfr_VMJFR_options;
|
||||
Java_oracle_jrockit_jfr_VMJFR_init;
|
||||
Java_oracle_jrockit_jfr_VMJFR_addConstPool;
|
||||
Java_oracle_jrockit_jfr_VMJFR_removeConstPool;
|
||||
Java_oracle_jrockit_jfr_VMJFR_storeConstPool;
|
||||
Java_oracle_jrockit_jfr_VMJFR_classID0;
|
||||
Java_oracle_jrockit_jfr_VMJFR_stackTraceID;
|
||||
Java_oracle_jrockit_jfr_VMJFR_threadID;
|
||||
Java_oracle_jrockit_jfr_VMJFR_rotate;
|
||||
Java_oracle_jrockit_jfr_VMJFR_shutdown;
|
||||
Java_oracle_jrockit_jfr_VMJFR_start;
|
||||
Java_oracle_jrockit_jfr_VMJFR_stop;
|
||||
Java_oracle_jrockit_jfr_VMJFR_buffer;
|
||||
Java_oracle_jrockit_jfr_VMJFR_flush;
|
||||
Java_oracle_jrockit_jfr_VMJFR_write;
|
||||
Java_oracle_jrockit_jfr_VMJFR_add;
|
||||
Java_oracle_jrockit_jfr_VMJFR_remove;
|
||||
Java_oracle_jrockit_jfr_VMJFR_setThreshold;
|
||||
Java_oracle_jrockit_jfr_VMJFR_setPeriod;
|
||||
Java_oracle_jrockit_jfr_VMJFR_getPeriod;
|
||||
Java_oracle_jrockit_jfr_VMJFR_descriptors;
|
||||
Java_oracle_jrockit_jfr_VMJFR_retransformClasses0;
|
||||
JNI_OnLoad;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
@ -19,7 +19,6 @@ java.xml
|
||||
java.xml.crypto
|
||||
jdk.charsets
|
||||
jdk.deploy
|
||||
jdk.deploy.osx
|
||||
jdk.httpserver
|
||||
jdk.jfr
|
||||
jdk.jsobject
|
||||
@ -28,6 +27,7 @@ jdk.vm.cds
|
||||
jdk.vm.ci
|
||||
jdk.management
|
||||
jdk.management.cmm
|
||||
jdk.management.jfr
|
||||
jdk.management.resource
|
||||
jdk.naming.rmi
|
||||
jdk.sctp
|
||||
|
||||
@ -81,9 +81,8 @@ final class ProcessHandleImpl implements ProcessHandle {
|
||||
ThreadGroup systemThreadGroup = tg;
|
||||
|
||||
ThreadFactory threadFactory = grimReaper -> {
|
||||
// Our thread stack requirement is quite modest.
|
||||
Thread t = new Thread(systemThreadGroup, grimReaper,
|
||||
"process reaper", 32768);
|
||||
long stackSize = Boolean.getBoolean("jdk.lang.processReaperUseDefaultStackSize") ? 0 : 32768;
|
||||
Thread t = new Thread(systemThreadGroup, grimReaper, "process reaper", stackSize);
|
||||
t.setDaemon(true);
|
||||
// A small attempt (probably futile) to avoid priority inversion
|
||||
t.setPriority(Thread.MAX_PRIORITY);
|
||||
|
||||
@ -42,6 +42,7 @@ import java.util.regex.PatternSyntaxException;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.StreamSupport;
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
|
||||
/**
|
||||
* The {@code String} class represents character strings. All
|
||||
@ -119,7 +120,18 @@ import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
public final class String
|
||||
implements java.io.Serializable, Comparable<String>, CharSequence {
|
||||
|
||||
/** The value is used for character storage. */
|
||||
/**
|
||||
* The value is used for character storage.
|
||||
*
|
||||
* @implNote This field is trusted by the VM, and is a subject to
|
||||
* constant folding if String instance is constant. Overwriting this
|
||||
* field after construction will cause problems.
|
||||
*
|
||||
* Additionally, it is marked with {@link Stable} to trust the contents
|
||||
* of the array. No other facility in JDK provides this functionality (yet).
|
||||
* {@link Stable} is safe here, because value is never null.
|
||||
*/
|
||||
@Stable
|
||||
private final byte[] value;
|
||||
|
||||
/**
|
||||
@ -129,6 +141,9 @@ public final class String
|
||||
* LATIN1
|
||||
* UTF16
|
||||
*
|
||||
* @implNote This field is trusted by the VM, and is a subject to
|
||||
* constant folding if String instance is constant. Overwriting this
|
||||
* field after construction will cause problems.
|
||||
*/
|
||||
private final byte coder;
|
||||
|
||||
@ -1222,30 +1237,12 @@ public final class String
|
||||
public int compare(String s1, String s2) {
|
||||
byte v1[] = s1.value;
|
||||
byte v2[] = s2.value;
|
||||
int n1 = s1.length();
|
||||
int n2 = s2.length();
|
||||
boolean s1IsLatin1 = s1.isLatin1();
|
||||
boolean s2IsLatin1 = s2.isLatin1();
|
||||
int min = Math.min(n1, n2);
|
||||
for (int i = 0; i < min; i++) {
|
||||
char c1 = s1IsLatin1 ? StringLatin1.getChar(v1, i)
|
||||
: StringUTF16.getChar(v1, i);
|
||||
char c2 = s2IsLatin1 ? StringLatin1.getChar(v2, i)
|
||||
: StringUTF16.getChar(v2, i);
|
||||
if (c1 != c2) {
|
||||
c1 = Character.toUpperCase(c1);
|
||||
c2 = Character.toUpperCase(c2);
|
||||
if (c1 != c2) {
|
||||
c1 = Character.toLowerCase(c1);
|
||||
c2 = Character.toLowerCase(c2);
|
||||
if (c1 != c2) {
|
||||
// No overflow because of numeric promotion
|
||||
return c1 - c2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s1.coder() == s2.coder()) {
|
||||
return s1.isLatin1() ? StringLatin1.compareToCI(v1, v2)
|
||||
: StringUTF16.compareToCI(v1, v2);
|
||||
}
|
||||
return n1 - n2;
|
||||
return s1.isLatin1() ? StringLatin1.compareToCI_UTF16(v1, v2)
|
||||
: StringUTF16.compareToCI_Latin1(v1, v2);
|
||||
}
|
||||
|
||||
/** Replaces the de-serialized object. */
|
||||
|
||||
@ -128,6 +128,48 @@ final class StringLatin1 {
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
public static int compareToCI(byte[] value, byte[] other) {
|
||||
int len1 = value.length;
|
||||
int len2 = other.length;
|
||||
int lim = Math.min(len1, len2);
|
||||
for (int k = 0; k < lim; k++) {
|
||||
if (value[k] != other[k]) {
|
||||
char c1 = (char) CharacterDataLatin1.instance.toUpperCase(getChar(value, k));
|
||||
char c2 = (char) CharacterDataLatin1.instance.toUpperCase(getChar(other, k));
|
||||
if (c1 != c2) {
|
||||
c1 = (char) CharacterDataLatin1.instance.toLowerCase(c1);
|
||||
c2 = (char) CharacterDataLatin1.instance.toLowerCase(c2);
|
||||
if (c1 != c2) {
|
||||
return c1 - c2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
public static int compareToCI_UTF16(byte[] value, byte[] other) {
|
||||
int len1 = length(value);
|
||||
int len2 = StringUTF16.length(other);
|
||||
int lim = Math.min(len1, len2);
|
||||
for (int k = 0; k < lim; k++) {
|
||||
char c1 = getChar(value, k);
|
||||
char c2 = StringUTF16.getChar(other, k);
|
||||
if (c1 != c2) {
|
||||
c1 = Character.toUpperCase(c1);
|
||||
c2 = Character.toUpperCase(c2);
|
||||
if (c1 != c2) {
|
||||
c1 = Character.toLowerCase(c1);
|
||||
c2 = Character.toLowerCase(c2);
|
||||
if (c1 != c2) {
|
||||
return c1 - c2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
public static int hashCode(byte[] value) {
|
||||
int h = 0;
|
||||
for (byte v : value) {
|
||||
|
||||
@ -270,6 +270,50 @@ final class StringUTF16 {
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
public static int compareToCI(byte[] value, byte[] other) {
|
||||
int len1 = length(value);
|
||||
int len2 = length(other);
|
||||
int lim = Math.min(len1, len2);
|
||||
for (int k = 0; k < lim; k++) {
|
||||
char c1 = getChar(value, k);
|
||||
char c2 = getChar(other, k);
|
||||
if (c1 != c2) {
|
||||
c1 = Character.toUpperCase(c1);
|
||||
c2 = Character.toUpperCase(c2);
|
||||
if (c1 != c2) {
|
||||
c1 = Character.toLowerCase(c1);
|
||||
c2 = Character.toLowerCase(c2);
|
||||
if (c1 != c2) {
|
||||
return c1 - c2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
public static int compareToCI_Latin1(byte[] value, byte[] other) {
|
||||
int len1 = length(value);
|
||||
int len2 = StringLatin1.length(other);
|
||||
int lim = Math.min(len1, len2);
|
||||
for (int k = 0; k < lim; k++) {
|
||||
char c1 = getChar(value, k);
|
||||
char c2 = StringLatin1.getChar(other, k);
|
||||
if (c1 != c2) {
|
||||
c1 = Character.toUpperCase(c1);
|
||||
c2 = Character.toUpperCase(c2);
|
||||
if (c1 != c2) {
|
||||
c1 = Character.toLowerCase(c1);
|
||||
c2 = Character.toLowerCase(c2);
|
||||
if (c1 != c2) {
|
||||
return c1 - c2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
public static int hashCode(byte[] value) {
|
||||
int h = 0;
|
||||
int length = value.length >> 1;
|
||||
|
||||
@ -30,7 +30,7 @@ import java.lang.reflect.Field;
|
||||
import static java.lang.invoke.MethodHandleNatives.Constants.*;
|
||||
import static java.lang.invoke.MethodHandleStatics.*;
|
||||
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
import jdk.internal.ref.Cleaner;
|
||||
import jdk.internal.ref.CleanerFactory;
|
||||
|
||||
/**
|
||||
* The JVM interface for the method handles package is all here.
|
||||
@ -68,10 +68,12 @@ class MethodHandleNatives {
|
||||
|
||||
static CallSiteContext make(CallSite cs) {
|
||||
final CallSiteContext newContext = new CallSiteContext();
|
||||
// Cleaner is attached to CallSite instance and it clears native structures allocated for CallSite context.
|
||||
// Though the CallSite can become unreachable, its Context is retained by the Cleaner instance (which is
|
||||
// referenced from Cleaner class) until cleanup is performed.
|
||||
Cleaner.create(cs, newContext);
|
||||
// CallSite instance is tracked by a Cleanable which clears native
|
||||
// structures allocated for CallSite context. Though the CallSite can
|
||||
// become unreachable, its Context is retained by the Cleanable instance
|
||||
// (which is referenced from Cleaner instance which is referenced from
|
||||
// CleanerFactory class) until cleanup is performed.
|
||||
CleanerFactory.cleaner().register(cs, newContext);
|
||||
return newContext;
|
||||
}
|
||||
|
||||
|
||||
@ -91,7 +91,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||
* can call with more than 255 slots. This limits the number of static and
|
||||
* dynamic arguments one can pass to bootstrap method. Since there are potential
|
||||
* concatenation strategies that use {@code MethodHandle} combinators, we need
|
||||
* to reserve a few empty slots on the parameter lists to to capture the
|
||||
* to reserve a few empty slots on the parameter lists to capture the
|
||||
* temporal results. This is why bootstrap methods in this factory do not accept
|
||||
* more than 200 argument slots. Users requiring more than 200 argument slots in
|
||||
* concatenation are expected to split the large concatenation in smaller
|
||||
|
||||
@ -25,10 +25,11 @@
|
||||
|
||||
package java.lang.ref;
|
||||
|
||||
import jdk.internal.ref.CleanerImpl;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import jdk.internal.ref.CleanerImpl;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* {@code Cleaner} manages a set of object references and corresponding cleaning actions.
|
||||
@ -135,7 +136,12 @@ public final class Cleaner {
|
||||
final CleanerImpl impl;
|
||||
|
||||
static {
|
||||
CleanerImpl.setCleanerImplAccess((Cleaner c) -> c.impl);
|
||||
CleanerImpl.setCleanerImplAccess(new Function<Cleaner, CleanerImpl>() {
|
||||
@Override
|
||||
public CleanerImpl apply(Cleaner cleaner) {
|
||||
return cleaner.impl;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -44,7 +44,6 @@ import java.util.ServiceConfigurationError;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import jdk.internal.misc.VM;
|
||||
import sun.misc.ASCIICaseInsensitiveComparator;
|
||||
import sun.nio.cs.StandardCharsets;
|
||||
import sun.nio.cs.ThreadLocalCoders;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
@ -579,7 +578,7 @@ public abstract class Charset
|
||||
public SortedMap<String,Charset> run() {
|
||||
TreeMap<String,Charset> m =
|
||||
new TreeMap<>(
|
||||
ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER);
|
||||
String.CASE_INSENSITIVE_ORDER);
|
||||
put(standardProvider.charsets(), m);
|
||||
CharsetProvider[] ecps = ExtendedProviderHolder.extendedProviders;
|
||||
for (CharsetProvider ecp :ecps) {
|
||||
|
||||
@ -2728,7 +2728,7 @@ public class Collections {
|
||||
* Set s2 = m2.keySet(); // Needn't be in synchronized block
|
||||
* ...
|
||||
* synchronized (m) { // Synchronizing on m, not m2 or s2!
|
||||
* Iterator i = s.iterator(); // Must be in synchronized block
|
||||
* Iterator i = s2.iterator(); // Must be in synchronized block
|
||||
* while (i.hasNext())
|
||||
* foo(i.next());
|
||||
* }
|
||||
|
||||
@ -34,9 +34,9 @@ import java.util.Set;
|
||||
import java.util.Collection;
|
||||
import java.util.AbstractSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
import java.util.Comparator;
|
||||
import sun.misc.ASCIICaseInsensitiveComparator;
|
||||
|
||||
/**
|
||||
* The Attributes class maps Manifest attribute names to associated string
|
||||
@ -501,7 +501,7 @@ public class Attributes implements Map<Object,Object>, Cloneable {
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof Name) {
|
||||
Comparator<String> c = ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER;
|
||||
Comparator<String> c = String.CASE_INSENSITIVE_ORDER;
|
||||
return c.compare(name, ((Name)o).name) == 0;
|
||||
} else {
|
||||
return false;
|
||||
@ -513,7 +513,7 @@ public class Attributes implements Map<Object,Object>, Cloneable {
|
||||
*/
|
||||
public int hashCode() {
|
||||
if (hashCode == -1) {
|
||||
hashCode = ASCIICaseInsensitiveComparator.lowerCaseHashCode(name);
|
||||
hashCode = name.toLowerCase(Locale.ROOT).hashCode();
|
||||
}
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@ -128,8 +128,12 @@ public final class InnocuousThread extends Thread {
|
||||
}
|
||||
final ThreadGroup root = group;
|
||||
INNOCUOUSTHREADGROUP = AccessController.doPrivileged(
|
||||
(PrivilegedAction<ThreadGroup>) () ->
|
||||
{ return new ThreadGroup(root, "InnocuousThreadGroup"); });
|
||||
new PrivilegedAction<ThreadGroup>() {
|
||||
@Override
|
||||
public ThreadGroup run() {
|
||||
return new ThreadGroup(root, "InnocuousThreadGroup");
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
|
||||
@ -782,6 +782,46 @@ public final class Unsafe {
|
||||
Object expected,
|
||||
Object x);
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final native Object compareAndExchangeObjectVolatile(Object o, long offset,
|
||||
Object expected,
|
||||
Object x);
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final Object compareAndExchangeObjectAcquire(Object o, long offset,
|
||||
Object expected,
|
||||
Object x) {
|
||||
return compareAndExchangeObjectVolatile(o, offset, expected, x);
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final Object compareAndExchangeObjectRelease(Object o, long offset,
|
||||
Object expected,
|
||||
Object x) {
|
||||
return compareAndExchangeObjectVolatile(o, offset, expected, x);
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final boolean weakCompareAndSwapObject(Object o, long offset,
|
||||
Object expected,
|
||||
Object x) {
|
||||
return compareAndSwapObject(o, offset, expected, x);
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final boolean weakCompareAndSwapObjectAcquire(Object o, long offset,
|
||||
Object expected,
|
||||
Object x) {
|
||||
return compareAndSwapObject(o, offset, expected, x);
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final boolean weakCompareAndSwapObjectRelease(Object o, long offset,
|
||||
Object expected,
|
||||
Object x) {
|
||||
return compareAndSwapObject(o, offset, expected, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates Java variable to {@code x} if it is currently
|
||||
* holding {@code expected}.
|
||||
@ -796,6 +836,46 @@ public final class Unsafe {
|
||||
int expected,
|
||||
int x);
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final native int compareAndExchangeIntVolatile(Object o, long offset,
|
||||
int expected,
|
||||
int x);
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final int compareAndExchangeIntAcquire(Object o, long offset,
|
||||
int expected,
|
||||
int x) {
|
||||
return compareAndExchangeIntVolatile(o, offset, expected, x);
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final int compareAndExchangeIntRelease(Object o, long offset,
|
||||
int expected,
|
||||
int x) {
|
||||
return compareAndExchangeIntVolatile(o, offset, expected, x);
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final boolean weakCompareAndSwapInt(Object o, long offset,
|
||||
int expected,
|
||||
int x) {
|
||||
return compareAndSwapInt(o, offset, expected, x);
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final boolean weakCompareAndSwapIntAcquire(Object o, long offset,
|
||||
int expected,
|
||||
int x) {
|
||||
return compareAndSwapInt(o, offset, expected, x);
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final boolean weakCompareAndSwapIntRelease(Object o, long offset,
|
||||
int expected,
|
||||
int x) {
|
||||
return compareAndSwapInt(o, offset, expected, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates Java variable to {@code x} if it is currently
|
||||
* holding {@code expected}.
|
||||
@ -810,6 +890,46 @@ public final class Unsafe {
|
||||
long expected,
|
||||
long x);
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final native long compareAndExchangeLongVolatile(Object o, long offset,
|
||||
long expected,
|
||||
long x);
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final long compareAndExchangeLongAcquire(Object o, long offset,
|
||||
long expected,
|
||||
long x) {
|
||||
return compareAndExchangeLongVolatile(o, offset, expected, x);
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final long compareAndExchangeLongRelease(Object o, long offset,
|
||||
long expected,
|
||||
long x) {
|
||||
return compareAndExchangeLongVolatile(o, offset, expected, x);
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final boolean weakCompareAndSwapLong(Object o, long offset,
|
||||
long expected,
|
||||
long x) {
|
||||
return compareAndSwapLong(o, offset, expected, x);
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final boolean weakCompareAndSwapLongAcquire(Object o, long offset,
|
||||
long expected,
|
||||
long x) {
|
||||
return compareAndSwapLong(o, offset, expected, x);
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final boolean weakCompareAndSwapLongRelease(Object o, long offset,
|
||||
long expected,
|
||||
long x) {
|
||||
return compareAndSwapLong(o, offset, expected, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a reference value from a given Java variable, with volatile
|
||||
* load semantics. Otherwise identical to {@link #getObject(Object, long)}
|
||||
@ -908,6 +1028,224 @@ public final class Unsafe {
|
||||
@HotSpotIntrinsicCandidate
|
||||
public native void putOrderedLong(Object o, long offset, long x);
|
||||
|
||||
/** Acquire version of {@link #getObjectVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final Object getObjectAcquire(Object o, long offset) {
|
||||
return getObjectVolatile(o, offset);
|
||||
}
|
||||
|
||||
/** Acquire version of {@link #getBooleanVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final boolean getBooleanAcquire(Object o, long offset) {
|
||||
return getBooleanVolatile(o, offset);
|
||||
}
|
||||
|
||||
/** Acquire version of {@link #getByteVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final byte getByteAcquire(Object o, long offset) {
|
||||
return getByteVolatile(o, offset);
|
||||
}
|
||||
|
||||
/** Acquire version of {@link #getShortVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final short getShortAcquire(Object o, long offset) {
|
||||
return getShortVolatile(o, offset);
|
||||
}
|
||||
|
||||
/** Acquire version of {@link #getCharVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final char getCharAcquire(Object o, long offset) {
|
||||
return getCharVolatile(o, offset);
|
||||
}
|
||||
|
||||
/** Acquire version of {@link #getIntVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final int getIntAcquire(Object o, long offset) {
|
||||
return getIntVolatile(o, offset);
|
||||
}
|
||||
|
||||
/** Acquire version of {@link #getFloatVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final float getFloatAcquire(Object o, long offset) {
|
||||
return getFloatVolatile(o, offset);
|
||||
}
|
||||
|
||||
/** Acquire version of {@link #getLongVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final long getLongAcquire(Object o, long offset) {
|
||||
return getLongVolatile(o, offset);
|
||||
}
|
||||
|
||||
/** Acquire version of {@link #getDoubleVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final double getDoubleAcquire(Object o, long offset) {
|
||||
return getDoubleVolatile(o, offset);
|
||||
}
|
||||
|
||||
/** Release version of {@link #putObjectVolatile(Object, long, Object)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putObjectRelease(Object o, long offset, Object x) {
|
||||
putObjectVolatile(o, offset, x);
|
||||
}
|
||||
|
||||
/** Release version of {@link #putBooleanVolatile(Object, long, boolean)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putBooleanRelease(Object o, long offset, boolean x) {
|
||||
putBooleanVolatile(o, offset, x);
|
||||
}
|
||||
|
||||
/** Release version of {@link #putByteVolatile(Object, long, byte)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putByteRelease(Object o, long offset, byte x) {
|
||||
putByteVolatile(o, offset, x);
|
||||
}
|
||||
|
||||
/** Release version of {@link #putShortVolatile(Object, long, short)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putShortRelease(Object o, long offset, short x) {
|
||||
putShortVolatile(o, offset, x);
|
||||
}
|
||||
|
||||
/** Release version of {@link #putCharVolatile(Object, long, char)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putCharRelease(Object o, long offset, char x) {
|
||||
putCharVolatile(o, offset, x);
|
||||
}
|
||||
|
||||
/** Release version of {@link #putIntVolatile(Object, long, int)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putIntRelease(Object o, long offset, int x) {
|
||||
putIntVolatile(o, offset, x);
|
||||
}
|
||||
|
||||
/** Release version of {@link #putFloatVolatile(Object, long, float)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putFloatRelease(Object o, long offset, float x) {
|
||||
putFloatVolatile(o, offset, x);
|
||||
}
|
||||
|
||||
/** Release version of {@link #putLongVolatile(Object, long, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putLongRelease(Object o, long offset, long x) {
|
||||
putLongVolatile(o, offset, x);
|
||||
}
|
||||
|
||||
/** Release version of {@link #putDoubleVolatile(Object, long, double)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putDoubleRelease(Object o, long offset, double x) {
|
||||
putDoubleVolatile(o, offset, x);
|
||||
}
|
||||
|
||||
// ------------------------------ Opaque --------------------------------------
|
||||
|
||||
/** Opaque version of {@link #getObjectVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final Object getObjectOpaque(Object o, long offset) {
|
||||
return getObjectVolatile(o, offset);
|
||||
}
|
||||
|
||||
/** Opaque version of {@link #getBooleanVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final boolean getBooleanOpaque(Object o, long offset) {
|
||||
return getBooleanVolatile(o, offset);
|
||||
}
|
||||
|
||||
/** Opaque version of {@link #getByteVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final byte getByteOpaque(Object o, long offset) {
|
||||
return getByteVolatile(o, offset);
|
||||
}
|
||||
|
||||
/** Opaque version of {@link #getShortVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final short getShortOpaque(Object o, long offset) {
|
||||
return getShortVolatile(o, offset);
|
||||
}
|
||||
|
||||
/** Opaque version of {@link #getCharVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final char getCharOpaque(Object o, long offset) {
|
||||
return getCharVolatile(o, offset);
|
||||
}
|
||||
|
||||
/** Opaque version of {@link #getIntVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final int getIntOpaque(Object o, long offset) {
|
||||
return getIntVolatile(o, offset);
|
||||
}
|
||||
|
||||
/** Opaque version of {@link #getFloatVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final float getFloatOpaque(Object o, long offset) {
|
||||
return getFloatVolatile(o, offset);
|
||||
}
|
||||
|
||||
/** Opaque version of {@link #getLongVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final long getLongOpaque(Object o, long offset) {
|
||||
return getLongVolatile(o, offset);
|
||||
}
|
||||
|
||||
/** Opaque version of {@link #getDoubleVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final double getDoubleOpaque(Object o, long offset) {
|
||||
return getDoubleVolatile(o, offset);
|
||||
}
|
||||
|
||||
/** Opaque version of {@link #putObjectVolatile(Object, long, Object)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putObjectOpaque(Object o, long offset, Object x) {
|
||||
putObjectVolatile(o, offset, x);
|
||||
}
|
||||
|
||||
/** Opaque version of {@link #putBooleanVolatile(Object, long, boolean)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putBooleanOpaque(Object o, long offset, boolean x) {
|
||||
putBooleanVolatile(o, offset, x);
|
||||
}
|
||||
|
||||
/** Opaque version of {@link #putByteVolatile(Object, long, byte)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putByteOpaque(Object o, long offset, byte x) {
|
||||
putByteVolatile(o, offset, x);
|
||||
}
|
||||
|
||||
/** Opaque version of {@link #putShortVolatile(Object, long, short)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putShortOpaque(Object o, long offset, short x) {
|
||||
putShortVolatile(o, offset, x);
|
||||
}
|
||||
|
||||
/** Opaque version of {@link #putCharVolatile(Object, long, char)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putCharOpaque(Object o, long offset, char x) {
|
||||
putCharVolatile(o, offset, x);
|
||||
}
|
||||
|
||||
/** Opaque version of {@link #putIntVolatile(Object, long, int)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putIntOpaque(Object o, long offset, int x) {
|
||||
putIntVolatile(o, offset, x);
|
||||
}
|
||||
|
||||
/** Opaque version of {@link #putFloatVolatile(Object, long, float)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putFloatOpaque(Object o, long offset, float x) {
|
||||
putFloatVolatile(o, offset, x);
|
||||
}
|
||||
|
||||
/** Opaque version of {@link #putLongVolatile(Object, long, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putLongOpaque(Object o, long offset, long x) {
|
||||
putLongVolatile(o, offset, x);
|
||||
}
|
||||
|
||||
/** Opaque version of {@link #putDoubleVolatile(Object, long, double)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putDoubleOpaque(Object o, long offset, double x) {
|
||||
putDoubleVolatile(o, offset, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unblocks the given thread blocked on {@code park}, or, if it is
|
||||
* not blocked, causes the subsequent call to {@code park} not to
|
||||
@ -1100,6 +1438,23 @@ public final class Unsafe {
|
||||
@HotSpotIntrinsicCandidate
|
||||
public native void fullFence();
|
||||
|
||||
/**
|
||||
* Ensures that loads before the fence will not be reordered with
|
||||
* loads after the fence.
|
||||
*/
|
||||
public final void loadLoadFence() {
|
||||
loadFence();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that stores before the fence will not be reordered with
|
||||
* stores after the fence.
|
||||
*/
|
||||
public final void storeStoreFence() {
|
||||
storeFence();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Throws IllegalAccessError; for use by the VM for access control
|
||||
* error support.
|
||||
|
||||
@ -31,6 +31,7 @@ import java.lang.ref.ReferenceQueue;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Function;
|
||||
|
||||
import jdk.internal.misc.InnocuousThread;
|
||||
@ -39,7 +40,7 @@ import jdk.internal.misc.InnocuousThread;
|
||||
* CleanerImpl manages a set of object references and corresponding cleaning actions.
|
||||
* CleanerImpl provides the functionality of {@link java.lang.ref.Cleaner}.
|
||||
*/
|
||||
public final class CleanerImpl {
|
||||
public final class CleanerImpl implements Runnable {
|
||||
|
||||
/**
|
||||
* An object to access the CleanerImpl from a Cleaner; set by Cleaner init.
|
||||
@ -103,7 +104,7 @@ public final class CleanerImpl {
|
||||
}
|
||||
// schedule a nop cleaning action for the cleaner, so the associated thread
|
||||
// will continue to run at least until the cleaner is reclaimable.
|
||||
new PhantomCleanableRef(cleaner, cleaner, () -> {});
|
||||
new CleanerCleanable(cleaner);
|
||||
|
||||
if (threadFactory == null) {
|
||||
threadFactory = CleanerImpl.InnocuousThreadFactory.factory();
|
||||
@ -112,7 +113,7 @@ public final class CleanerImpl {
|
||||
// now that there's at least one cleaning action, for the cleaner,
|
||||
// we can start the associated thread, which runs until
|
||||
// all cleaning actions have been run.
|
||||
Thread thread = threadFactory.newThread(this::run);
|
||||
Thread thread = threadFactory.newThread(this);
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
}
|
||||
@ -128,7 +129,8 @@ public final class CleanerImpl {
|
||||
* If the thread is a ManagedLocalsThread, the threadlocals
|
||||
* are erased before each cleanup
|
||||
*/
|
||||
private void run() {
|
||||
@Override
|
||||
public void run() {
|
||||
Thread t = Thread.currentThread();
|
||||
InnocuousThread mlThread = (t instanceof InnocuousThread)
|
||||
? (InnocuousThread) t
|
||||
@ -147,10 +149,9 @@ public final class CleanerImpl {
|
||||
if (ref != null) {
|
||||
ref.clean();
|
||||
}
|
||||
} catch (InterruptedException i) {
|
||||
continue; // ignore the interruption
|
||||
} catch (Throwable e) {
|
||||
// ignore exceptions from the cleanup action
|
||||
// (including interruption of cleanup thread)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -320,14 +321,32 @@ public final class CleanerImpl {
|
||||
return factory;
|
||||
}
|
||||
|
||||
final AtomicInteger cleanerThreadNumber = new AtomicInteger();
|
||||
|
||||
public Thread newThread(Runnable r) {
|
||||
return AccessController.doPrivileged((PrivilegedAction<Thread>) () -> {
|
||||
Thread t = new InnocuousThread(r);
|
||||
t.setPriority(Thread.MAX_PRIORITY - 2);
|
||||
t.setName("Cleaner-" + t.getId());
|
||||
return t;
|
||||
return AccessController.doPrivileged(new PrivilegedAction<Thread>() {
|
||||
@Override
|
||||
public Thread run() {
|
||||
Thread t = new InnocuousThread(r);
|
||||
t.setPriority(Thread.MAX_PRIORITY - 2);
|
||||
t.setName("Cleaner-" + cleanerThreadNumber.getAndIncrement());
|
||||
return t;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A PhantomCleanable implementation for tracking the Cleaner itself.
|
||||
*/
|
||||
static final class CleanerCleanable extends PhantomCleanable<Cleaner> {
|
||||
CleanerCleanable(Cleaner cleaner) {
|
||||
super(cleaner, cleaner);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performCleanup() {
|
||||
// no action
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.misc;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/** Implements a locale and case insensitive comparator suitable for
|
||||
strings that are known to only contain ASCII characters. Some
|
||||
tables internal to the JDK contain only ASCII data and are using
|
||||
the "generalized" java.lang.String case-insensitive comparator
|
||||
which converts each character to both upper and lower case. */
|
||||
|
||||
public class ASCIICaseInsensitiveComparator implements Comparator<String> {
|
||||
public static final Comparator<String> CASE_INSENSITIVE_ORDER =
|
||||
new ASCIICaseInsensitiveComparator();
|
||||
|
||||
public int compare(String s1, String s2) {
|
||||
int n1=s1.length(), n2=s2.length();
|
||||
int minLen = n1 < n2 ? n1 : n2;
|
||||
for (int i=0; i < minLen; i++) {
|
||||
char c1 = s1.charAt(i);
|
||||
char c2 = s2.charAt(i);
|
||||
assert c1 <= '\u007F' && c2 <= '\u007F';
|
||||
if (c1 != c2) {
|
||||
c1 = (char)toLower(c1);
|
||||
c2 = (char)toLower(c2);
|
||||
if (c1 != c2) {
|
||||
return c1 - c2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return n1 - n2;
|
||||
}
|
||||
|
||||
/**
|
||||
* A case insensitive hash code method to go with the case insensitive
|
||||
* compare() method.
|
||||
*
|
||||
* Returns a hash code for this ASCII string as if it were lower case.
|
||||
*
|
||||
* returns same answer as:<p>
|
||||
* <code>s.toLowerCase(Locale.US).hashCode();</code><p>
|
||||
* but does not allocate memory (it does NOT have the special
|
||||
* case Turkish rules).
|
||||
*
|
||||
* @param s a String to compute the hashcode on.
|
||||
* @return a hash code value for this object.
|
||||
*/
|
||||
public static int lowerCaseHashCode(String s) {
|
||||
int h = 0;
|
||||
int len = s.length();
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
h = 31*h + toLower(s.charAt(i));
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/* If java.util.regex.ASCII ever becomes public or sun.*, use its code instead:*/
|
||||
static boolean isLower(int ch) {
|
||||
return ((ch-'a')|('z'-ch)) >= 0;
|
||||
}
|
||||
|
||||
static boolean isUpper(int ch) {
|
||||
return ((ch-'A')|('Z'-ch)) >= 0;
|
||||
}
|
||||
|
||||
static int toLower(int ch) {
|
||||
return isUpper(ch) ? (ch + 0x20) : ch;
|
||||
}
|
||||
|
||||
static int toUpper(int ch) {
|
||||
return isLower(ch) ? (ch - 0x20) : ch;
|
||||
}
|
||||
}
|
||||
@ -26,7 +26,7 @@
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import jdk.internal.ref.Cleaner;
|
||||
import jdk.internal.ref.CleanerFactory;
|
||||
|
||||
|
||||
/**
|
||||
@ -101,7 +101,7 @@ class IOVecWrapper {
|
||||
}
|
||||
if (wrapper == null) {
|
||||
wrapper = new IOVecWrapper(size);
|
||||
Cleaner.create(wrapper, new Deallocator(wrapper.vecArray));
|
||||
CleanerFactory.cleaner().register(wrapper, new Deallocator(wrapper.vecArray));
|
||||
cached.set(wrapper);
|
||||
}
|
||||
return wrapper;
|
||||
|
||||
@ -33,7 +33,6 @@ import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.*;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import jdk.internal.ref.Cleaner;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
|
||||
|
||||
@ -71,8 +71,8 @@ class NativeBuffer {
|
||||
return size;
|
||||
}
|
||||
|
||||
Cleaner cleaner() {
|
||||
return cleaner;
|
||||
void free() {
|
||||
cleaner.clean();
|
||||
}
|
||||
|
||||
// not synchronized; only safe for use by thread-local caches
|
||||
|
||||
@ -107,14 +107,14 @@ class NativeBuffers {
|
||||
for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) {
|
||||
NativeBuffer existing = buffers[i];
|
||||
if (existing.size() < buffer.size()) {
|
||||
existing.cleaner().clean();
|
||||
existing.free();
|
||||
buffers[i] = buffer;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// free it
|
||||
buffer.cleaner().clean();
|
||||
buffer.free();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -700,7 +700,7 @@ static final class CertificateStatus extends HandshakeMessage
|
||||
* OCSP response data is provided.
|
||||
*/
|
||||
CertificateStatus(StatusRequestType type, X509Certificate[] chain,
|
||||
Map<X509Certificate, byte[]> responses) throws SSLException {
|
||||
Map<X509Certificate, byte[]> responses) {
|
||||
statusType = type;
|
||||
encodedResponsesLen = 0;
|
||||
encodedResponses = new ArrayList<>(chain.length);
|
||||
@ -715,7 +715,7 @@ static final class CertificateStatus extends HandshakeMessage
|
||||
encodedResponses.add(respDER);
|
||||
encodedResponsesLen = 3 + respDER.length;
|
||||
} else {
|
||||
throw new SSLHandshakeException("Zero-length or null " +
|
||||
throw new IllegalArgumentException("Zero-length or null " +
|
||||
"OCSP Response");
|
||||
}
|
||||
} else if (statusType == StatusRequestType.OCSP_MULTI) {
|
||||
@ -732,8 +732,8 @@ static final class CertificateStatus extends HandshakeMessage
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new SSLHandshakeException("Unsupported StatusResponseType: " +
|
||||
statusType);
|
||||
throw new IllegalArgumentException(
|
||||
"Unsupported StatusResponseType: " + statusType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -36,7 +36,6 @@ import java.security.spec.ECParameterSpec;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import javax.net.ssl.*;
|
||||
|
||||
import sun.security.action.GetLongAction;
|
||||
@ -67,7 +66,6 @@ final class ServerHandshaker extends Handshaker {
|
||||
|
||||
// our authentication info
|
||||
private X509Certificate[] certs;
|
||||
private Map<X509Certificate, byte[]> responseMap;
|
||||
private PrivateKey privateKey;
|
||||
|
||||
private Object serviceCreds;
|
||||
@ -118,7 +116,6 @@ final class ServerHandshaker extends Handshaker {
|
||||
LegacyAlgorithmConstraints.PROPERTY_TLS_LEGACY_ALGS,
|
||||
new SSLAlgorithmDecomposer());
|
||||
|
||||
private boolean staplingActive = false;
|
||||
private long statusRespTimeout;
|
||||
|
||||
static {
|
||||
@ -578,16 +575,6 @@ final class ServerHandshaker extends Handshaker {
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the client has asserted the status_request[_v2] extension(s)
|
||||
CertStatusReqExtension statReqExt = (CertStatusReqExtension)
|
||||
mesg.extensions.get(ExtensionType.EXT_STATUS_REQUEST);
|
||||
CertStatusReqListV2Extension statReqExtV2 =
|
||||
(CertStatusReqListV2Extension)mesg.extensions.get(
|
||||
ExtensionType.EXT_STATUS_REQUEST_V2);
|
||||
// Keep stapling active if at least one of the extensions has been set
|
||||
staplingActive = sslContext.isStaplingEnabled(false) &&
|
||||
(statReqExt != null || statReqExtV2 != null);
|
||||
|
||||
/*
|
||||
* FIRST, construct the ServerHello using the options and priorities
|
||||
* from the ClientHello. Update the (pending) cipher spec as we do
|
||||
@ -883,79 +870,17 @@ final class ServerHandshaker extends Handshaker {
|
||||
m1.extensions.add(maxFragLenExt);
|
||||
}
|
||||
|
||||
StatusRequestType statReqType = null;
|
||||
StatusRequest statReqData = null;
|
||||
if (staplingActive && !resumingSession) {
|
||||
ExtensionType statusRespExt = ExtensionType.EXT_STATUS_REQUEST;
|
||||
|
||||
// Determine which type of stapling we are doing and assert the
|
||||
// proper extension in the server hello.
|
||||
// Favor status_request_v2 over status_request and ocsp_multi
|
||||
// over ocsp.
|
||||
// If multiple ocsp or ocsp_multi types exist, select the first
|
||||
// instance of a given type
|
||||
if (statReqExtV2 != null) { // RFC 6961 stapling
|
||||
statusRespExt = ExtensionType.EXT_STATUS_REQUEST_V2;
|
||||
List<CertStatusReqItemV2> reqItems =
|
||||
statReqExtV2.getRequestItems();
|
||||
int ocspIdx = -1;
|
||||
int ocspMultiIdx = -1;
|
||||
for (int pos = 0; pos < reqItems.size(); pos++) {
|
||||
CertStatusReqItemV2 item = reqItems.get(pos);
|
||||
if (ocspIdx < 0 && item.getType() ==
|
||||
StatusRequestType.OCSP) {
|
||||
ocspIdx = pos;
|
||||
} else if (ocspMultiIdx < 0 && item.getType() ==
|
||||
StatusRequestType.OCSP_MULTI) {
|
||||
ocspMultiIdx = pos;
|
||||
}
|
||||
}
|
||||
if (ocspMultiIdx >= 0) {
|
||||
statReqType = reqItems.get(ocspMultiIdx).getType();
|
||||
statReqData = reqItems.get(ocspMultiIdx).getRequest();
|
||||
} else if (ocspIdx >= 0) {
|
||||
statReqType = reqItems.get(ocspIdx).getType();
|
||||
statReqData = reqItems.get(ocspIdx).getRequest();
|
||||
} else {
|
||||
// Some unknown type. We will not do stapling for
|
||||
// this connection since we cannot understand the
|
||||
// requested type.
|
||||
staplingActive = false;
|
||||
}
|
||||
} else { // RFC 6066 stapling
|
||||
statReqType = StatusRequestType.OCSP;
|
||||
statReqData = statReqExt.getRequest();
|
||||
}
|
||||
|
||||
if (statReqType != null && statReqData != null) {
|
||||
StatusResponseManager statRespMgr =
|
||||
sslContext.getStatusResponseManager();
|
||||
if (statRespMgr != null) {
|
||||
responseMap = statRespMgr.get(statReqType, statReqData,
|
||||
certs, statusRespTimeout, TimeUnit.MILLISECONDS);
|
||||
if (!responseMap.isEmpty()) {
|
||||
// We now can safely assert status_request[_v2] in our
|
||||
// ServerHello, and know for certain that we can provide
|
||||
// responses back to this client for this connection.
|
||||
if (statusRespExt == ExtensionType.EXT_STATUS_REQUEST) {
|
||||
m1.extensions.add(new CertStatusReqExtension());
|
||||
} else if (statusRespExt ==
|
||||
ExtensionType.EXT_STATUS_REQUEST_V2) {
|
||||
m1.extensions.add(
|
||||
new CertStatusReqListV2Extension());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// This should not happen if stapling is active, but
|
||||
// if lazy initialization of the StatusResponseManager
|
||||
// doesn't occur we should turn off stapling.
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println("Warning: lazy initialization " +
|
||||
"of the StatusResponseManager failed. " +
|
||||
"Stapling has been disabled.");
|
||||
staplingActive = false;
|
||||
}
|
||||
}
|
||||
StaplingParameters staplingParams = processStapling(mesg);
|
||||
if (staplingParams != null) {
|
||||
// We now can safely assert status_request[_v2] in our
|
||||
// ServerHello, and know for certain that we can provide
|
||||
// responses back to this client for this connection.
|
||||
if (staplingParams.statusRespExt ==
|
||||
ExtensionType.EXT_STATUS_REQUEST) {
|
||||
m1.extensions.add(new CertStatusReqExtension());
|
||||
} else if (staplingParams.statusRespExt ==
|
||||
ExtensionType.EXT_STATUS_REQUEST_V2) {
|
||||
m1.extensions.add(new CertStatusReqListV2Extension());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1031,24 +956,15 @@ final class ServerHandshaker extends Handshaker {
|
||||
* supports status stapling and there is at least one response to
|
||||
* return to the client.
|
||||
*/
|
||||
if (staplingActive && !responseMap.isEmpty()) {
|
||||
try {
|
||||
CertificateStatus csMsg = new CertificateStatus(statReqType,
|
||||
certs, responseMap);
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
csMsg.print(System.out);
|
||||
}
|
||||
csMsg.write(output);
|
||||
handshakeState.update(csMsg, resumingSession);
|
||||
responseMap = null;
|
||||
} catch (SSLException ssle) {
|
||||
// We don't want the exception to be fatal, we just won't
|
||||
// send the message if we fail on construction.
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println("Failed during CertificateStatus " +
|
||||
"construction: " + ssle);
|
||||
}
|
||||
if (staplingParams != null) {
|
||||
CertificateStatus csMsg = new CertificateStatus(
|
||||
staplingParams.statReqType, certs,
|
||||
staplingParams.responseMap);
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
csMsg.print(System.out);
|
||||
}
|
||||
csMsg.write(output);
|
||||
handshakeState.update(csMsg, resumingSession);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2078,4 +1994,121 @@ final class ServerHandshaker extends Handshaker {
|
||||
|
||||
session.setPeerCertificates(peerCerts);
|
||||
}
|
||||
|
||||
private StaplingParameters processStapling(ClientHello mesg) {
|
||||
StaplingParameters params = null;
|
||||
ExtensionType ext;
|
||||
StatusRequestType type = null;
|
||||
StatusRequest req = null;
|
||||
Map<X509Certificate, byte[]> responses;
|
||||
|
||||
// If this feature has not been enabled, then no more processing
|
||||
// is necessary. Also we will only staple if we're doing a full
|
||||
// handshake.
|
||||
if (!sslContext.isStaplingEnabled(false) || resumingSession) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if the client has asserted the status_request[_v2] extension(s)
|
||||
CertStatusReqExtension statReqExt = (CertStatusReqExtension)
|
||||
mesg.extensions.get(ExtensionType.EXT_STATUS_REQUEST);
|
||||
CertStatusReqListV2Extension statReqExtV2 =
|
||||
(CertStatusReqListV2Extension)mesg.extensions.get(
|
||||
ExtensionType.EXT_STATUS_REQUEST_V2);
|
||||
// Keep processing only if either status_request or status_request_v2
|
||||
// has been sent in the ClientHello.
|
||||
if (statReqExt == null && statReqExtV2 == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Determine which type of stapling we are doing and assert the
|
||||
// proper extension in the server hello.
|
||||
// Favor status_request_v2 over status_request and ocsp_multi
|
||||
// over ocsp.
|
||||
// If multiple ocsp or ocsp_multi types exist, select the first
|
||||
// instance of a given type
|
||||
ext = ExtensionType.EXT_STATUS_REQUEST;
|
||||
if (statReqExtV2 != null) { // RFC 6961 stapling
|
||||
ext = ExtensionType.EXT_STATUS_REQUEST_V2;
|
||||
List<CertStatusReqItemV2> reqItems =
|
||||
statReqExtV2.getRequestItems();
|
||||
int ocspIdx = -1;
|
||||
int ocspMultiIdx = -1;
|
||||
for (int pos = 0; pos < reqItems.size(); pos++) {
|
||||
CertStatusReqItemV2 item = reqItems.get(pos);
|
||||
if (ocspIdx < 0 && item.getType() ==
|
||||
StatusRequestType.OCSP) {
|
||||
ocspIdx = pos;
|
||||
} else if (ocspMultiIdx < 0 && item.getType() ==
|
||||
StatusRequestType.OCSP_MULTI) {
|
||||
ocspMultiIdx = pos;
|
||||
}
|
||||
}
|
||||
if (ocspMultiIdx >= 0) {
|
||||
type = reqItems.get(ocspMultiIdx).getType();
|
||||
req = reqItems.get(ocspMultiIdx).getRequest();
|
||||
} else if (ocspIdx >= 0) {
|
||||
type = reqItems.get(ocspIdx).getType();
|
||||
req = reqItems.get(ocspIdx).getRequest();
|
||||
}
|
||||
} else { // RFC 6066 stapling
|
||||
type = StatusRequestType.OCSP;
|
||||
req = statReqExt.getRequest();
|
||||
}
|
||||
|
||||
// If, after walking through the extensions we were unable to
|
||||
// find a suitable StatusRequest, then stapling is disabled.
|
||||
// Both statReqType and statReqData must have been set to continue.
|
||||
if (type == null || req == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the OCSP responses from the StatusResponseManager
|
||||
StatusResponseManager statRespMgr =
|
||||
sslContext.getStatusResponseManager();
|
||||
if (statRespMgr != null) {
|
||||
responses = statRespMgr.get(type, req, certs, statusRespTimeout,
|
||||
TimeUnit.MILLISECONDS);
|
||||
if (!responses.isEmpty()) {
|
||||
// If this RFC 6066-style stapling (SSL cert only) then the
|
||||
// response cannot be zero length
|
||||
if (type == StatusRequestType.OCSP) {
|
||||
byte[] respDER = responses.get(certs[0]);
|
||||
if (respDER == null || respDER.length <= 0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
params = new StaplingParameters(ext, type, req, responses);
|
||||
}
|
||||
} else {
|
||||
// This should not happen, but if lazy initialization of the
|
||||
// StatusResponseManager doesn't occur we should turn off stapling.
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println("Warning: lazy initialization " +
|
||||
"of the StatusResponseManager failed. " +
|
||||
"Stapling has been disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner class used to hold stapling parameters needed by the handshaker
|
||||
* when stapling is active.
|
||||
*/
|
||||
private class StaplingParameters {
|
||||
private final ExtensionType statusRespExt;
|
||||
private final StatusRequestType statReqType;
|
||||
private final StatusRequest statReqData;
|
||||
private final Map<X509Certificate, byte[]> responseMap;
|
||||
|
||||
StaplingParameters(ExtensionType ext, StatusRequestType type,
|
||||
StatusRequest req, Map<X509Certificate, byte[]> responses) {
|
||||
statusRespExt = ext;
|
||||
statReqType = type;
|
||||
statReqData = req;
|
||||
responseMap = responses;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -1952,6 +1952,7 @@ JNI_OnUnload(JavaVM *vm, void *reserved);
|
||||
#define JNI_VERSION_1_4 0x00010004
|
||||
#define JNI_VERSION_1_6 0x00010006
|
||||
#define JNI_VERSION_1_8 0x00010008
|
||||
#define JNI_VERSION_9 0x00090000
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@ -463,7 +463,7 @@ class WindowsWatchService
|
||||
}
|
||||
CloseHandle(key.handle());
|
||||
closeAttachedEvent(key.overlappedAddress());
|
||||
key.buffer().cleaner().clean();
|
||||
key.buffer().free();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -469,7 +469,9 @@ GetJavaProperties(JNIEnv* env)
|
||||
* Windows Server 2008 R2 6 1 (!VER_NT_WORKSTATION)
|
||||
* Windows 8 6 2 (VER_NT_WORKSTATION)
|
||||
* Windows Server 2012 6 2 (!VER_NT_WORKSTATION)
|
||||
* Windows Server 2012 R2 6 3 (!VER_NT_WORKSTATION)
|
||||
* Windows 10 10 0 (VER_NT_WORKSTATION)
|
||||
* Windows Server 2016 10 0 (!VER_NT_WORKSTATION)
|
||||
*
|
||||
* This mapping will presumably be augmented as new Windows
|
||||
* versions are released.
|
||||
@ -543,6 +545,7 @@ GetJavaProperties(JNIEnv* env)
|
||||
}
|
||||
} else {
|
||||
switch (minorVersion) {
|
||||
case 0: sprops.os_name = "Windows Server 2016"; break;
|
||||
default: sprops.os_name = "Windows NT (unknown)";
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,21 +214,21 @@ class Exchange {
|
||||
.sendHeadersAsync()
|
||||
.thenCompose((Void v) -> {
|
||||
// send body and get response at same time
|
||||
exchImpl.sendBodyAsync();
|
||||
return exchImpl.getResponseAsync(null);
|
||||
return exchImpl.sendBodyAsync()
|
||||
.thenCompose(exchImpl::getResponseAsync);
|
||||
})
|
||||
.thenCompose((HttpResponseImpl r1) -> {
|
||||
int rcode = r1.statusCode();
|
||||
CompletableFuture<HttpResponseImpl> cf =
|
||||
checkForUpgradeAsync(r1, exchImpl);
|
||||
if (cf != null) {
|
||||
return cf;
|
||||
} else {
|
||||
Exchange.this.response = r1;
|
||||
logResponse(r1);
|
||||
return CompletableFuture.completedFuture(r1);
|
||||
}
|
||||
})
|
||||
.thenCompose((HttpResponseImpl r1) -> {
|
||||
int rcode = r1.statusCode();
|
||||
CompletableFuture<HttpResponseImpl> cf =
|
||||
checkForUpgradeAsync(r1, exchImpl);
|
||||
if (cf != null) {
|
||||
return cf;
|
||||
} else {
|
||||
Exchange.this.response = r1;
|
||||
logResponse(r1);
|
||||
return CompletableFuture.completedFuture(r1);
|
||||
}
|
||||
})
|
||||
.thenApply((HttpResponseImpl response) -> {
|
||||
this.response = response;
|
||||
logResponse(response);
|
||||
|
||||
@ -30,19 +30,17 @@ import java.net.ProxySelector;
|
||||
import java.net.URI;
|
||||
import static java.net.http.Utils.BUFSIZE;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.SelectableChannel;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import static java.nio.channels.SelectionKey.OP_CONNECT;
|
||||
import static java.nio.channels.SelectionKey.OP_READ;
|
||||
import static java.nio.channels.SelectionKey.OP_WRITE;
|
||||
import java.nio.channels.Selector;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
@ -72,12 +70,6 @@ class HttpClientImpl extends HttpClient implements BufferHandler {
|
||||
private static final ThreadFactory defaultFactory = Executors.defaultThreadFactory();
|
||||
private final LinkedList<TimeoutEvent> timeouts;
|
||||
|
||||
//@Override
|
||||
void debugPrint() {
|
||||
selmgr.debugPrint();
|
||||
client2.debugPrint();
|
||||
}
|
||||
|
||||
public static HttpClientImpl create(HttpClientBuilderImpl builder) {
|
||||
HttpClientImpl impl = new HttpClientImpl(builder);
|
||||
impl.start();
|
||||
@ -173,19 +165,15 @@ class HttpClientImpl extends HttpClient implements BufferHandler {
|
||||
// Main loop for this client's selector
|
||||
|
||||
class SelectorManager extends Thread {
|
||||
|
||||
final Selector selector;
|
||||
boolean closed;
|
||||
|
||||
final List<AsyncEvent> readyList;
|
||||
final List<AsyncEvent> registrations;
|
||||
|
||||
List<AsyncEvent> debugList;
|
||||
|
||||
SelectorManager() throws IOException {
|
||||
readyList = new LinkedList<>();
|
||||
registrations = new LinkedList<>();
|
||||
debugList = new LinkedList<>();
|
||||
selector = Selector.open();
|
||||
}
|
||||
|
||||
@ -216,13 +204,6 @@ class HttpClientImpl extends HttpClient implements BufferHandler {
|
||||
return c;
|
||||
}
|
||||
|
||||
synchronized void debugPrint() {
|
||||
System.err.println("Selecting on:");
|
||||
for (AsyncEvent e : debugList) {
|
||||
System.err.println(opvals(e.interestOps()));
|
||||
}
|
||||
}
|
||||
|
||||
String opvals(int i) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if ((i & OP_READ) != 0)
|
||||
@ -239,14 +220,18 @@ class HttpClientImpl extends HttpClient implements BufferHandler {
|
||||
try {
|
||||
while (true) {
|
||||
synchronized (this) {
|
||||
debugList = copy(registrations);
|
||||
for (AsyncEvent exchange : registrations) {
|
||||
SelectableChannel c = exchange.channel();
|
||||
try {
|
||||
c.configureBlocking(false);
|
||||
c.register(selector,
|
||||
exchange.interestOps(),
|
||||
exchange);
|
||||
SelectionKey key = c.keyFor(selector);
|
||||
SelectorAttachment sa;
|
||||
if (key == null) {
|
||||
sa = new SelectorAttachment(c, selector);
|
||||
} else {
|
||||
sa = (SelectorAttachment)key.attachment();
|
||||
}
|
||||
sa.register(exchange);
|
||||
} catch (IOException e) {
|
||||
Log.logError("HttpClientImpl: " + e);
|
||||
c.close();
|
||||
@ -266,11 +251,10 @@ class HttpClientImpl extends HttpClient implements BufferHandler {
|
||||
Set<SelectionKey> keys = selector.selectedKeys();
|
||||
|
||||
for (SelectionKey key : keys) {
|
||||
if (key.isReadable() || key.isConnectable() || key.isWritable()) {
|
||||
key.cancel();
|
||||
AsyncEvent exchange = (AsyncEvent) key.attachment();
|
||||
readyList.add(exchange);
|
||||
}
|
||||
SelectorAttachment sa = (SelectorAttachment)key.attachment();
|
||||
int eventsOccurred = key.readyOps();
|
||||
sa.events(eventsOccurred).forEach(readyList::add);
|
||||
sa.resetInterestOps(eventsOccurred);
|
||||
}
|
||||
selector.selectNow(); // complete cancellation
|
||||
selector.selectedKeys().clear();
|
||||
@ -305,6 +289,80 @@ class HttpClientImpl extends HttpClient implements BufferHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks multiple user level registrations associated with one NIO
|
||||
* registration (SelectionKey). In this implementation, registrations
|
||||
* are one-off and when an event is posted the registration is cancelled
|
||||
* until explicitly registered again.
|
||||
*
|
||||
* <p> No external synchronization required as this class is only used
|
||||
* by the SelectorManager thread. One of these objects required per
|
||||
* connection.
|
||||
*/
|
||||
private static class SelectorAttachment {
|
||||
private final SelectableChannel chan;
|
||||
private final Selector selector;
|
||||
private final ArrayList<AsyncEvent> pending;
|
||||
private int interestops;
|
||||
|
||||
SelectorAttachment(SelectableChannel chan, Selector selector) {
|
||||
this.pending = new ArrayList<>();
|
||||
this.chan = chan;
|
||||
this.selector = selector;
|
||||
}
|
||||
|
||||
void register(AsyncEvent e) throws ClosedChannelException {
|
||||
int newops = e.interestOps();
|
||||
boolean reRegister = (interestops & newops) != newops;
|
||||
interestops |= newops;
|
||||
pending.add(e);
|
||||
if (reRegister) {
|
||||
// first time registration happens here also
|
||||
chan.register(selector, interestops, this);
|
||||
}
|
||||
}
|
||||
|
||||
int interestOps() {
|
||||
return interestops;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Stream<AsyncEvents> containing only events that are
|
||||
* registered with the given {@code interestop}.
|
||||
*/
|
||||
Stream<AsyncEvent> events(int interestop) {
|
||||
return pending.stream()
|
||||
.filter(ev -> (ev.interestOps() & interestop) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes any events with the given {@code interestop}, and if no
|
||||
* events remaining, cancels the associated SelectionKey.
|
||||
*/
|
||||
void resetInterestOps(int interestop) {
|
||||
int newops = 0;
|
||||
|
||||
Iterator<AsyncEvent> itr = pending.iterator();
|
||||
while (itr.hasNext()) {
|
||||
AsyncEvent event = itr.next();
|
||||
int evops = event.interestOps();
|
||||
if ((evops & interestop) != 0) {
|
||||
itr.remove();
|
||||
} else {
|
||||
newops |= evops;
|
||||
}
|
||||
}
|
||||
|
||||
interestops = newops;
|
||||
SelectionKey key = chan.keyFor(selector);
|
||||
if (newops == 0) {
|
||||
key.cancel();
|
||||
} else {
|
||||
key.interestOps(newops);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a HttpRequest associated with this group.
|
||||
*
|
||||
@ -425,18 +483,9 @@ class HttpClientImpl extends HttpClient implements BufferHandler {
|
||||
}
|
||||
}
|
||||
iter.add(event);
|
||||
//debugPrintList("register");
|
||||
selmgr.wakeupSelector();
|
||||
}
|
||||
|
||||
void debugPrintList(String s) {
|
||||
System.err.printf("%s: {", s);
|
||||
for (TimeoutEvent e : timeouts) {
|
||||
System.err.printf("(%d,%d) ", e.delta, e.timeval);
|
||||
}
|
||||
System.err.println("}");
|
||||
}
|
||||
|
||||
synchronized void signalTimeouts(long then) {
|
||||
if (timeouts.isEmpty()) {
|
||||
return;
|
||||
@ -462,7 +511,6 @@ class HttpClientImpl extends HttpClient implements BufferHandler {
|
||||
break;
|
||||
}
|
||||
}
|
||||
//debugPrintList("signalTimeouts");
|
||||
}
|
||||
|
||||
synchronized void cancelTimer(TimeoutEvent event) {
|
||||
|
||||
@ -82,7 +82,7 @@ import java.util.Properties;
|
||||
* attribute-value-assertions when specifying multiple attribute/value
|
||||
* pairs. (e.g. "," in age=65,gender=male).
|
||||
* <dt>jndi.syntax.separator.typeval
|
||||
* <dd>If present, specifies the string that separators attribute
|
||||
* <dd>If present, specifies the string that separates attribute
|
||||
* from value (e.g. "=" in "age=65")
|
||||
*</dl>
|
||||
* These properties are interpreted according to the following rules:
|
||||
|
||||
@ -33,7 +33,6 @@ import java.util.TreeMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import sun.misc.ASCIICaseInsensitiveComparator;
|
||||
|
||||
|
||||
/**
|
||||
@ -49,22 +48,22 @@ public class AbstractCharsetProvider
|
||||
/* Maps canonical names to class names
|
||||
*/
|
||||
private Map<String,String> classMap
|
||||
= new TreeMap<>(ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER);
|
||||
= new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
/* Maps alias names to canonical names
|
||||
*/
|
||||
private Map<String,String> aliasMap
|
||||
= new TreeMap<>(ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER);
|
||||
= new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
/* Maps canonical names to alias-name arrays
|
||||
*/
|
||||
private Map<String,String[]> aliasNameMap
|
||||
= new TreeMap<>(ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER);
|
||||
= new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
/* Maps canonical names to soft references that hold cached instances
|
||||
*/
|
||||
private Map<String,SoftReference<Charset>> cache
|
||||
= new TreeMap<>(ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER);
|
||||
= new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
private String packagePrefix;
|
||||
|
||||
|
||||
@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.apple.concurrent;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* Factory for {@link Executor}s and {@link ExecutorService}s backed by
|
||||
* libdispatch.
|
||||
*
|
||||
* Access is controlled through the Dispatch.getInstance() method, because
|
||||
* performed tasks occur on threads owned by libdispatch. These threads are
|
||||
* not owned by any particular AppContext or have any specific context
|
||||
* classloader installed.
|
||||
*
|
||||
* @since Java for Mac OS X 10.6 Update 2
|
||||
*/
|
||||
public final class Dispatch {
|
||||
/**
|
||||
* The priorities of the three default asynchronous queues.
|
||||
*/
|
||||
public enum Priority {
|
||||
LOW(-2), NORMAL(0), HIGH(2); // values from <dispatch/queue.h>
|
||||
|
||||
final int nativePriority;
|
||||
Priority(final int nativePriority) { this.nativePriority = nativePriority; }
|
||||
};
|
||||
|
||||
final static Dispatch instance = new Dispatch();
|
||||
|
||||
/**
|
||||
* Factory method returns an instnace of Dispatch if supported by the
|
||||
* underlying operating system, and if the caller's security manager
|
||||
* permits "canInvokeInSystemThreadGroup".
|
||||
*
|
||||
* @return a factory instance of Dispatch, or null if not available
|
||||
*/
|
||||
public static Dispatch getInstance() {
|
||||
checkSecurity();
|
||||
if (!LibDispatchNative.nativeIsDispatchSupported()) return null;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static void checkSecurity() {
|
||||
final SecurityManager security = System.getSecurityManager();
|
||||
if (security != null) security.checkPermission(new RuntimePermission("canInvokeInSystemThreadGroup"));
|
||||
}
|
||||
|
||||
private Dispatch() { }
|
||||
|
||||
/**
|
||||
* Creates an {@link Executor} that performs tasks asynchronously. The {@link Executor}
|
||||
* cannot be shutdown, and enqueued {@link Runnable}s cannot be canceled. Passing null
|
||||
* returns the {@link Priority.NORMAL} {@link Executor}.
|
||||
*
|
||||
* @param priority - the priority of the returned {@link Executor}
|
||||
* @return an asynchronous {@link Executor}
|
||||
*/
|
||||
public Executor getAsyncExecutor(Priority priority) {
|
||||
if (priority == null) priority = Priority.NORMAL;
|
||||
final long nativeQueue = LibDispatchNative.nativeCreateConcurrentQueue(priority.nativePriority);
|
||||
if (nativeQueue == 0L) return null;
|
||||
return new LibDispatchConcurrentQueue(nativeQueue);
|
||||
}
|
||||
|
||||
int queueIndex = 0;
|
||||
/**
|
||||
* Creates an {@link ExecutorService} that performs tasks synchronously in FIFO order.
|
||||
* Useful to protect a resource against concurrent modification, in lieu of a lock.
|
||||
* Passing null returns an {@link ExecutorService} with a uniquely labeled queue.
|
||||
*
|
||||
* @param label - a label to name the queue, shown in several debugging tools
|
||||
* @return a synchronous {@link ExecutorService}
|
||||
*/
|
||||
public ExecutorService createSerialExecutor(String label) {
|
||||
if (label == null) label = "";
|
||||
if (label.length() > 256) label = label.substring(0, 256);
|
||||
String queueName = "com.apple.java.concurrent.";
|
||||
if ("".equals(label)) {
|
||||
synchronized (this) {
|
||||
queueName += queueIndex++;
|
||||
}
|
||||
} else {
|
||||
queueName += label;
|
||||
}
|
||||
|
||||
final long nativeQueue = LibDispatchNative.nativeCreateSerialQueue(queueName);
|
||||
if (nativeQueue == 0) return null;
|
||||
return new LibDispatchSerialQueue(nativeQueue);
|
||||
}
|
||||
|
||||
Executor nonBlockingMainQueue = null;
|
||||
/**
|
||||
* Returns an {@link Executor} that performs the provided Runnables on the main queue of the process.
|
||||
* Runnables submitted to this {@link Executor} will not run until the AWT is started or another native toolkit is running a CFRunLoop or NSRunLoop on the main thread.
|
||||
*
|
||||
* Submitting a Runnable to this {@link Executor} does not wait for the Runnable to complete.
|
||||
* @return an asynchronous {@link Executor} that is backed by the main queue
|
||||
*/
|
||||
public synchronized Executor getNonBlockingMainQueueExecutor() {
|
||||
if (nonBlockingMainQueue != null) return nonBlockingMainQueue;
|
||||
return nonBlockingMainQueue = new LibDispatchMainQueue.ASync();
|
||||
}
|
||||
|
||||
Executor blockingMainQueue = null;
|
||||
/**
|
||||
* Returns an {@link Executor} that performs the provided Runnables on the main queue of the process.
|
||||
* Runnables submitted to this {@link Executor} will not run until the AWT is started or another native toolkit is running a CFRunLoop or NSRunLoop on the main thread.
|
||||
*
|
||||
* Submitting a Runnable to this {@link Executor} will block until the Runnable has completed.
|
||||
* @return an {@link Executor} that is backed by the main queue
|
||||
*/
|
||||
public synchronized Executor getBlockingMainQueueExecutor() {
|
||||
if (blockingMainQueue != null) return blockingMainQueue;
|
||||
return blockingMainQueue = new LibDispatchMainQueue.Sync();
|
||||
}
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.apple.concurrent;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
class LibDispatchConcurrentQueue extends LibDispatchQueue implements Executor {
|
||||
LibDispatchConcurrentQueue(final long queuePtr) {
|
||||
super(queuePtr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final Runnable task) {
|
||||
LibDispatchNative.nativeExecuteAsync(ptr, task);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void dispose() {
|
||||
// should not dispose the default concurrent queues
|
||||
}
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.apple.concurrent;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
abstract class LibDispatchMainQueue extends LibDispatchQueue implements Executor {
|
||||
public LibDispatchMainQueue() {
|
||||
super(LibDispatchNative.nativeGetMainQueue());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void dispose() {
|
||||
// should not dispose the main queue
|
||||
}
|
||||
|
||||
static class Sync extends LibDispatchMainQueue {
|
||||
@Override
|
||||
public void execute(final Runnable task) {
|
||||
LibDispatchNative.nativeExecuteSync(ptr, task);
|
||||
}
|
||||
}
|
||||
|
||||
static class ASync extends LibDispatchMainQueue {
|
||||
@Override
|
||||
public void execute(final Runnable task) {
|
||||
LibDispatchNative.nativeExecuteAsync(ptr, task);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.apple.concurrent;
|
||||
|
||||
final class LibDispatchNative {
|
||||
static {
|
||||
java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
System.loadLibrary("osx");
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static native boolean nativeIsDispatchSupported();
|
||||
static native long nativeGetMainQueue();
|
||||
static native long nativeCreateConcurrentQueue(int priority);
|
||||
static native long nativeCreateSerialQueue(String name);
|
||||
static native void nativeReleaseQueue(long nativeQueue);
|
||||
static native void nativeExecuteAsync(long nativeQueue, Runnable task);
|
||||
static native void nativeExecuteSync(long nativeQueue, Runnable task);
|
||||
|
||||
private LibDispatchNative() { }
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.apple.concurrent;
|
||||
|
||||
class LibDispatchQueue extends LibDispatchRetainedResource {
|
||||
LibDispatchQueue(final long queuePtr) {
|
||||
super(queuePtr);
|
||||
}
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.apple.concurrent;
|
||||
|
||||
class LibDispatchRetainedResource {
|
||||
protected long ptr;
|
||||
|
||||
protected LibDispatchRetainedResource(final long ptr) {
|
||||
this.ptr = ptr;
|
||||
}
|
||||
|
||||
protected synchronized void dispose() {
|
||||
if (ptr != 0) LibDispatchNative.nativeReleaseQueue(ptr);
|
||||
ptr = 0;
|
||||
}
|
||||
|
||||
protected void finalize() throws Throwable {
|
||||
dispose();
|
||||
}
|
||||
}
|
||||
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.apple.concurrent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
class LibDispatchSerialQueue extends AbstractExecutorService {
|
||||
static final int RUNNING = 0;
|
||||
static final int SHUTDOWN = 1;
|
||||
// static final int STOP = 2; // not supported by GCD
|
||||
static final int TERMINATED = 3;
|
||||
|
||||
final Object lock = new Object();
|
||||
LibDispatchQueue nativeQueueWrapper;
|
||||
volatile int runState;
|
||||
|
||||
LibDispatchSerialQueue(final long queuePtr) {
|
||||
nativeQueueWrapper = new LibDispatchQueue(queuePtr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final Runnable task) {
|
||||
if (nativeQueueWrapper == null) return;
|
||||
LibDispatchNative.nativeExecuteAsync(nativeQueueWrapper.ptr, task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShutdown() {
|
||||
return runState != RUNNING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTerminated() {
|
||||
return runState == TERMINATED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
synchronized (lock) {
|
||||
if (runState != RUNNING) return;
|
||||
|
||||
runState = SHUTDOWN;
|
||||
execute(new Runnable() {
|
||||
public void run() {
|
||||
synchronized (lock) {
|
||||
runState = TERMINATED;
|
||||
lock.notifyAll(); // for the benefit of awaitTermination()
|
||||
}
|
||||
}
|
||||
});
|
||||
nativeQueueWrapper = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Runnable> shutdownNow() {
|
||||
shutdown();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean awaitTermination(final long timeout, final TimeUnit unit) throws InterruptedException {
|
||||
if (runState == TERMINATED) return true;
|
||||
|
||||
final long millis = unit.toMillis(timeout);
|
||||
if (millis <= 0) return false;
|
||||
|
||||
synchronized (lock) {
|
||||
if (runState == TERMINATED) return true;
|
||||
lock.wait(timeout);
|
||||
if (runState == TERMINATED) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
Apple-specific implementations of the java.util.concurrent.* API based on libdispatch.
|
||||
</body>
|
||||
</html>
|
||||
@ -1,174 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Must include this before JavaNativeFoundation.h to get jni.h from build
|
||||
*/
|
||||
#include "jni.h"
|
||||
#include "jni_util.h"
|
||||
|
||||
#import "com_apple_concurrent_LibDispatchNative.h"
|
||||
|
||||
#import <dispatch/dispatch.h>
|
||||
#import <JavaNativeFoundation/JavaNativeFoundation.h>
|
||||
|
||||
/*
|
||||
* Declare library specific JNI_Onload entry if static build
|
||||
*/
|
||||
DEF_STATIC_JNI_OnLoad
|
||||
|
||||
/*
|
||||
* Class: com_apple_concurrent_LibDispatchNative
|
||||
* Method: nativeIsDispatchSupported
|
||||
* Signature: ()Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeIsDispatchSupported
|
||||
(JNIEnv *env, jclass clazz)
|
||||
{
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: com_apple_concurrent_LibDispatchNative
|
||||
* Method: nativeGetMainQueue
|
||||
* Signature: ()J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeGetMainQueue
|
||||
(JNIEnv *env, jclass clazz)
|
||||
{
|
||||
dispatch_queue_t queue = dispatch_get_main_queue();
|
||||
return ptr_to_jlong(queue);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: com_apple_concurrent_LibDispatchNative
|
||||
* Method: nativeCreateConcurrentQueue
|
||||
* Signature: (I)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeCreateConcurrentQueue
|
||||
(JNIEnv *env, jclass clazz, jint priority)
|
||||
{
|
||||
dispatch_queue_t queue = dispatch_get_global_queue((long)priority, 0);
|
||||
return ptr_to_jlong(queue);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: com_apple_concurrent_LibDispatchNative
|
||||
* Method: nativeCreateSerialQueue
|
||||
* Signature: (Ljava/lang/String;)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeCreateSerialQueue
|
||||
(JNIEnv *env, jclass clazz, jstring name)
|
||||
{
|
||||
if (name == NULL) return 0L;
|
||||
|
||||
jboolean isCopy;
|
||||
const char *queue_name = (*env)->GetStringUTFChars(env, name, &isCopy);
|
||||
dispatch_queue_t queue = dispatch_queue_create(queue_name, NULL);
|
||||
(*env)->ReleaseStringUTFChars(env, name, queue_name);
|
||||
|
||||
return ptr_to_jlong(queue);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: com_apple_concurrent_LibDispatchNative
|
||||
* Method: nativeReleaseQueue
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeReleaseQueue
|
||||
(JNIEnv *env, jclass clazz, jlong nativeQueue)
|
||||
{
|
||||
if (nativeQueue == 0L) return;
|
||||
dispatch_release((dispatch_queue_t)jlong_to_ptr(nativeQueue));
|
||||
}
|
||||
|
||||
|
||||
static JNF_CLASS_CACHE(jc_Runnable, "java/lang/Runnable");
|
||||
static JNF_MEMBER_CACHE(jm_run, jc_Runnable, "run", "()V");
|
||||
|
||||
static void perform_dispatch(JNIEnv *env, jlong nativeQueue, jobject runnable, void (*dispatch_fxn)(dispatch_queue_t, dispatch_block_t))
|
||||
{
|
||||
JNF_COCOA_ENTER(env);
|
||||
dispatch_queue_t queue = (dispatch_queue_t)jlong_to_ptr(nativeQueue);
|
||||
if (queue == NULL) return; // shouldn't happen
|
||||
|
||||
// create a global-ref around the Runnable, so it can be safely passed to the dispatch thread
|
||||
JNFJObjectWrapper *wrappedRunnable = [[JNFJObjectWrapper alloc] initWithJObject:runnable withEnv:env];
|
||||
|
||||
dispatch_fxn(queue, ^{
|
||||
// attach the dispatch thread to the JVM if necessary, and get an env
|
||||
JNFThreadContext ctx = JNFThreadDetachOnThreadDeath | JNFThreadSetSystemClassLoaderOnAttach | JNFThreadAttachAsDaemon;
|
||||
JNIEnv *blockEnv = JNFObtainEnv(&ctx);
|
||||
|
||||
JNF_COCOA_ENTER(blockEnv);
|
||||
|
||||
// call the user's runnable
|
||||
JNFCallObjectMethod(blockEnv, [wrappedRunnable jObject], jm_run);
|
||||
|
||||
// explicitly clear object while we have an env (it's cheaper that way)
|
||||
[wrappedRunnable setJObject:NULL withEnv:blockEnv];
|
||||
|
||||
JNF_COCOA_EXIT(blockEnv);
|
||||
|
||||
// let the env go, but leave the thread attached as a daemon
|
||||
JNFReleaseEnv(blockEnv, &ctx);
|
||||
});
|
||||
|
||||
// release this thread's interest in the Runnable, the block
|
||||
// will have retained the it's own interest above
|
||||
[wrappedRunnable release];
|
||||
|
||||
JNF_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: com_apple_concurrent_LibDispatchNative
|
||||
* Method: nativeExecuteAsync
|
||||
* Signature: (JLjava/lang/Runnable;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeExecuteAsync
|
||||
(JNIEnv *env, jclass clazz, jlong nativeQueue, jobject runnable)
|
||||
{
|
||||
// enqueues and returns
|
||||
perform_dispatch(env, nativeQueue, runnable, dispatch_async);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: com_apple_concurrent_LibDispatchNative
|
||||
* Method: nativeExecuteSync
|
||||
* Signature: (JLjava/lang/Runnable;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeExecuteSync
|
||||
(JNIEnv *env, jclass clazz, jlong nativeQueue, jobject runnable)
|
||||
{
|
||||
// blocks until the Runnable completes
|
||||
perform_dispatch(env, nativeQueue, runnable, dispatch_sync);
|
||||
}
|
||||
@ -334,9 +334,6 @@ javax/imageio/plugins/tiff/WriteToSequenceAfterAbort.java generic-all
|
||||
|
||||
# jdk_time
|
||||
|
||||
# 8134979
|
||||
java/time/tck/java/time/chrono/TCKJapaneseChronology.java generic-all
|
||||
|
||||
############################################################################
|
||||
|
||||
# jdk_tools
|
||||
|
||||
79
jdk/test/com/sun/jdi/RedefineAddPrivateMethod.sh
Normal file
79
jdk/test/com/sun/jdi/RedefineAddPrivateMethod.sh
Normal file
@ -0,0 +1,79 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
# @test
|
||||
# @bug 8149743
|
||||
# @summary crash when adding a breakpoint after redefining to add a private static method
|
||||
# @run shell RedefineAddPrivateMethod.sh
|
||||
|
||||
compileOptions=-g
|
||||
|
||||
createJavaFile()
|
||||
{
|
||||
cat <<EOF > $1.java.1
|
||||
public class $1 {
|
||||
static public void main(String[] args) {
|
||||
System.out.println("@1 breakpoint");
|
||||
System.out.println("@2 breakpoint");
|
||||
}
|
||||
|
||||
// @1 uncomment private static void test() {}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# This is called to feed cmds to jdb.
|
||||
dojdbCmds()
|
||||
{
|
||||
setBkpts @1
|
||||
runToBkpt @1
|
||||
redefineClass @1
|
||||
setBkpts @2
|
||||
runToBkpt @2
|
||||
cmd exitJdb
|
||||
}
|
||||
|
||||
|
||||
mysetup()
|
||||
{
|
||||
if [ -z "$TESTSRC" ] ; then
|
||||
TESTSRC=.
|
||||
fi
|
||||
|
||||
for ii in . $TESTSRC $TESTSRC/.. ; do
|
||||
if [ -r "$ii/ShellScaffold.sh" ] ; then
|
||||
. $ii/ShellScaffold.sh
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# You could replace this next line with the contents
|
||||
# of ShellScaffold.sh and this script will run just the same.
|
||||
mysetup
|
||||
|
||||
runit
|
||||
debuggeeFailIfPresent "Internal exception:"
|
||||
pass
|
||||
@ -752,6 +752,7 @@ abstract public class TestScaffold extends TargetAdapter {
|
||||
sr.addClassExclusionFilter("com.oracle.*");
|
||||
sr.addClassExclusionFilter("oracle.*");
|
||||
sr.addClassExclusionFilter("jdk.internal.*");
|
||||
sr.addClassExclusionFilter("jdk.jfr.*");
|
||||
sr.addCountFilter(1);
|
||||
sr.enable();
|
||||
StepEvent retEvent = (StepEvent)waitForRequestedEvent(sr);
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
* java.management
|
||||
* java.instrument
|
||||
* @run shell/timeout=240 MakeJAR2.sh NativeMethodPrefixAgent NativeMethodPrefixApp 'Can-Retransform-Classes: true' 'Can-Set-Native-Method-Prefix: true'
|
||||
* @run main/othervm -javaagent:NativeMethodPrefixAgent.jar NativeMethodPrefixApp
|
||||
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-CheckIntrinsics -javaagent:NativeMethodPrefixAgent.jar NativeMethodPrefixApp
|
||||
*/
|
||||
|
||||
import java.lang.instrument.*;
|
||||
|
||||
@ -29,7 +29,7 @@ import java.nio.file.Paths;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/* @test
|
||||
* @bug 8027351
|
||||
* @bug 8027351 8148940
|
||||
* @summary Basic test of the finalize method
|
||||
*/
|
||||
|
||||
@ -63,6 +63,19 @@ public class FinalizeOverride {
|
||||
while (finalizedCount.get() != (count+1)) {
|
||||
System.gc();
|
||||
System.runFinalization();
|
||||
// Running System.gc() and System.runFinalization() in a
|
||||
// tight loop can trigger frequent safepointing that slows
|
||||
// down the VM and, as a result, the test. (With the
|
||||
// HotSpot VM, the effect of frequent safepointing is
|
||||
// especially noticeable if the test is run with the
|
||||
// -Xcomp flag.) Sleeping for a second after every
|
||||
// garbage collection and finalization cycle gives the VM
|
||||
// time to make progress.
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("Main thread interrupted, continuing execution.");
|
||||
}
|
||||
}
|
||||
|
||||
if (privateFinalizeInvoked) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,6 +27,7 @@ import java.net.URLPermission;
|
||||
*
|
||||
* @test
|
||||
* @bug 8010464
|
||||
* @key intermittent
|
||||
* @library /lib/testlibrary/
|
||||
* @build jdk.testlibrary.SimpleSSLContext
|
||||
* @run main/othervm/java.security.policy=policy.1 URLTest one
|
||||
|
||||
103
jdk/test/java/net/httpclient/ShortRequestBody.java
Normal file
103
jdk/test/java/net/httpclient/ShortRequestBody.java
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.net.http.*;
|
||||
import java.net.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.function.LongConsumer;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8151441
|
||||
* @run main/othervm/timeout=10 ShortRequestBody
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exception was not being thrown
|
||||
*/
|
||||
public class ShortRequestBody {
|
||||
|
||||
static Server server;
|
||||
static String reqbody = "Hello world";
|
||||
|
||||
static String response = "HTTP/1.1 200 OK\r\nContent-length: 0\r\n\r\n";
|
||||
|
||||
static class RequestBody implements HttpRequest.BodyProcessor {
|
||||
public long onRequestStart(HttpRequest hr, LongConsumer flowController) {
|
||||
return reqbody.length() + 1; // wrong!
|
||||
}
|
||||
|
||||
public boolean onRequestBodyChunk(ByteBuffer buf) throws IOException {
|
||||
byte[] b = reqbody.getBytes();
|
||||
buf.put(b);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static void close(Closeable c) {
|
||||
try {
|
||||
if (c == null)
|
||||
return;
|
||||
c.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ServerSocket server = new ServerSocket(0);
|
||||
int port = server.getLocalPort();
|
||||
URI uri = new URI("http://127.0.0.1:" + port + "/");
|
||||
|
||||
HttpRequest request;
|
||||
HttpResponse r;
|
||||
Socket s = null;
|
||||
CompletableFuture<HttpResponse> cf1;
|
||||
try {
|
||||
cf1 = HttpRequest.create(uri)
|
||||
.body(new RequestBody())
|
||||
.GET()
|
||||
.responseAsync();
|
||||
|
||||
s = server.accept();
|
||||
s.getInputStream().readAllBytes();
|
||||
try (OutputStream os = s.getOutputStream()) {
|
||||
os.write(response.getBytes());
|
||||
} catch (IOException ee) {
|
||||
}
|
||||
|
||||
try {
|
||||
r = cf1.get(3, TimeUnit.SECONDS);
|
||||
throw new RuntimeException("Failed");
|
||||
} catch (TimeoutException e0) {
|
||||
throw new RuntimeException("Failed timeout");
|
||||
} catch (ExecutionException e) {
|
||||
System.err.println("OK");
|
||||
}
|
||||
} finally {
|
||||
HttpClient.getDefault().executorService().shutdownNow();
|
||||
close(s);
|
||||
close(server);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
jdk/test/java/net/httpclient/whitebox/TEST.properties
Normal file
3
jdk/test/java/net/httpclient/whitebox/TEST.properties
Normal file
@ -0,0 +1,3 @@
|
||||
TestNG.dirs = .
|
||||
|
||||
bootclasspath.dirs = /java/net/httpclient
|
||||
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8151299
|
||||
* @summary Http client SelectorManager overwriting read and write events
|
||||
*/
|
||||
package java.net.http;
|
||||
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import static java.lang.System.out;
|
||||
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Whitebox test of selector mechanics. Currently only a simple test
|
||||
* setting one read and one write event is done. It checks that the
|
||||
* write event occurs first, followed by the read event and then no
|
||||
* further events occur despite the conditions actually still existing.
|
||||
*/
|
||||
@Test
|
||||
public class SelectorTest {
|
||||
|
||||
AtomicInteger counter = new AtomicInteger();
|
||||
volatile boolean error;
|
||||
static final CountDownLatch finishingGate = new CountDownLatch(1);
|
||||
|
||||
String readSomeBytes(RawChannel chan) {
|
||||
try {
|
||||
ByteBuffer buf = ByteBuffer.allocate(1024);
|
||||
int t = chan.read(buf);
|
||||
if (t <= 0) {
|
||||
out.printf("chan read returned %d\n", t);
|
||||
return null;
|
||||
}
|
||||
byte[] bb = new byte[t];
|
||||
buf.get(bb);
|
||||
return new String(bb, US_ASCII);
|
||||
} catch (IOException ioe) {
|
||||
throw new UncheckedIOException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(timeOut = 10000)
|
||||
public void test() throws Exception {
|
||||
|
||||
try (ServerSocket server = new ServerSocket(0)) {
|
||||
int port = server.getLocalPort();
|
||||
|
||||
out.println("Listening on port " + server.getLocalPort());
|
||||
|
||||
TestServer t = new TestServer(server);
|
||||
t.start();
|
||||
out.println("Started server thread");
|
||||
|
||||
final RawChannel chan = getARawChannel(port);
|
||||
|
||||
chan.registerEvent(new RawChannel.NonBlockingEvent() {
|
||||
@Override
|
||||
public int interestOps() {
|
||||
return SelectionKey.OP_READ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle() {
|
||||
readSomeBytes(chan);
|
||||
out.printf("OP_READ\n");
|
||||
if (counter.get() != 1) {
|
||||
out.printf("OP_READ error counter = %d\n", counter);
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
chan.registerEvent(new RawChannel.NonBlockingEvent() {
|
||||
@Override
|
||||
public int interestOps() {
|
||||
return SelectionKey.OP_WRITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle() {
|
||||
out.printf("OP_WRITE\n");
|
||||
if (counter.get() != 0) {
|
||||
out.printf("OP_WRITE error counter = %d\n", counter);
|
||||
error = true;
|
||||
} else {
|
||||
ByteBuffer bb = ByteBuffer.wrap(TestServer.INPUT);
|
||||
counter.incrementAndGet();
|
||||
try {
|
||||
chan.write(bb);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
out.println("Events registered. Waiting");
|
||||
finishingGate.await(30, SECONDS);
|
||||
if (error)
|
||||
throw new RuntimeException("Error");
|
||||
else
|
||||
out.println("No error");
|
||||
}
|
||||
}
|
||||
|
||||
static RawChannel getARawChannel(int port) throws Exception {
|
||||
URI uri = URI.create("http://127.0.0.1:" + port + "/");
|
||||
out.println("client connecting to " + uri.toString());
|
||||
HttpRequest req = HttpRequest.create(uri).GET();
|
||||
HttpResponse r = req.response();
|
||||
r.body(HttpResponse.ignoreBody());
|
||||
return ((HttpResponseImpl) r).rawChannel();
|
||||
}
|
||||
|
||||
static class TestServer extends Thread {
|
||||
static final byte[] INPUT = "Hello world".getBytes(US_ASCII);
|
||||
static final byte[] OUTPUT = "Goodbye world".getBytes(US_ASCII);
|
||||
static final String FIRST_RESPONSE = "HTTP/1.1 200 OK\r\nContent-length: 0\r\n\r\n";
|
||||
final ServerSocket server;
|
||||
|
||||
TestServer(ServerSocket server) throws IOException {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try (Socket s = server.accept();
|
||||
InputStream is = s.getInputStream();
|
||||
OutputStream os = s.getOutputStream()) {
|
||||
|
||||
out.println("Got connection");
|
||||
readRequest(is);
|
||||
os.write(FIRST_RESPONSE.getBytes());
|
||||
read(is);
|
||||
write(os);
|
||||
Thread.sleep(1000);
|
||||
// send some more data, and make sure WRITE op does not get called
|
||||
write(os);
|
||||
out.println("TestServer exiting");
|
||||
SelectorTest.finishingGate.countDown();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// consumes the HTTP request
|
||||
static void readRequest(InputStream is) throws IOException {
|
||||
out.println("starting readRequest");
|
||||
byte[] buf = new byte[1024];
|
||||
String s = "";
|
||||
while (true) {
|
||||
int n = is.read(buf);
|
||||
if (n <= 0)
|
||||
throw new IOException("Error");
|
||||
s = s + new String(buf, 0, n);
|
||||
if (s.indexOf("\r\n\r\n") != -1)
|
||||
break;
|
||||
}
|
||||
out.println("returning from readRequest");
|
||||
}
|
||||
|
||||
static void read(InputStream is) throws IOException {
|
||||
out.println("starting read");
|
||||
for (int i = 0; i < INPUT.length; i++) {
|
||||
int c = is.read();
|
||||
if (c == -1)
|
||||
throw new IOException("closed");
|
||||
if (INPUT[i] != (byte) c)
|
||||
throw new IOException("Error. Expected:" + INPUT[i] + ", got:" + c);
|
||||
}
|
||||
out.println("returning from read");
|
||||
}
|
||||
|
||||
static void write(OutputStream os) throws IOException {
|
||||
out.println("doing write");
|
||||
os.write(OUTPUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,6 +24,7 @@
|
||||
/*
|
||||
* @test
|
||||
* @bug 4868820
|
||||
* @key intermittent
|
||||
* @summary IPv6 support for Windows XP and 2003 server
|
||||
*/
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4313882 4981129
|
||||
* @bug 4313882 4981129 8143610
|
||||
* @summary Unit test for datagram-socket-channel adaptors
|
||||
* @library ..
|
||||
* @key randomness
|
||||
@ -137,7 +137,7 @@ public class AdaptDatagramSocket {
|
||||
echoServer.getPort());
|
||||
test(address, 0, false, false);
|
||||
test(address, 0, false, true);
|
||||
test(address, 15000, false, false);
|
||||
test(address, Integer.MAX_VALUE, false, false);
|
||||
}
|
||||
try (TestServers.UdpDiscardServer discardServer
|
||||
= TestServers.UdpDiscardServer.startNewServer()) {
|
||||
|
||||
1
jdk/test/sample/TEST.properties
Normal file
1
jdk/test/sample/TEST.properties
Normal file
@ -0,0 +1 @@
|
||||
external.lib.roots = ../../
|
||||
@ -25,9 +25,9 @@
|
||||
/* @test
|
||||
* @summary Test chat server chatserver test
|
||||
*
|
||||
* @library ../../../src/sample/share/nio/chatserver
|
||||
* @library /src/sample/share/nio/chatserver
|
||||
* @build ChatTest ChatServer Client ClientReader DataReader MessageReader NameReader
|
||||
* @run main ChatTest
|
||||
* @run testng ChatTest
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
@ -38,10 +38,13 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class ChatTest {
|
||||
public static int listeningPort = 0;
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
@Test
|
||||
public static void doTest() throws Throwable {
|
||||
testStartStop();
|
||||
testPortOpen();
|
||||
testAsksForName();
|
||||
|
||||
@ -25,14 +25,16 @@
|
||||
/* @test
|
||||
* @summary Test MergeSort
|
||||
*
|
||||
* @library ../../../src/sample/share/forkjoin/mergesort
|
||||
* @library /src/sample/share/forkjoin/mergesort
|
||||
* @build MergeSortTest MergeDemo MergeSort
|
||||
* @run main MergeSortTest
|
||||
* @run testng MergeSortTest
|
||||
*/
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class MergeSortTest {
|
||||
private Random random;
|
||||
private MergeSort target;
|
||||
@ -42,7 +44,8 @@ public class MergeSortTest {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
@Test
|
||||
public static void doTest() {
|
||||
MergeSortTest test = new MergeSortTest(new Random(), new MergeSort(Runtime.getRuntime().availableProcessors() * 4));
|
||||
test.run();
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,7 +28,7 @@ import java.security.SignatureException;
|
||||
/*
|
||||
* @test
|
||||
* @bug 8050374
|
||||
* @key randomness
|
||||
* @key randomness intermittent
|
||||
* @summary This test validates signature verification
|
||||
* Signature.verify(byte[], int, int). The test uses RandomFactory to
|
||||
* get random set of clear text data to sign. After the signature
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user