--- a/jdk/make/gensrc/Gensrc-jdk.jdi.gmk Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/make/gensrc/Gensrc-jdk.jdi.gmk Thu Jan 14 20:57:33 2016 -0800
@@ -70,7 +70,7 @@
# Filter com.sun.jdi.connect.Connector
$(SUPPORT_OUTPUTDIR)/gensrc/jdk.jdi/META-INF/services/com.sun.jdi.connect.Connector: \
$(JDK_TOPDIR)/src/jdk.jdi/share/classes/META-INF/services/com.sun.jdi.connect.Connector \
- $(HOTSPOT_TOPDIR)/agent/src/share/classes/META-INF/services/com.sun.jdi.connect.Connector
+ $(HOTSPOT_TOPDIR)/src/jdk.hotspot.agent/share/classes/META-INF/services/com.sun.jdi.connect.Connector
$(process-provider)
# Copy the same service file into jdk.hotspot.agent so that they are kept the same.
--- a/jdk/make/lib/CoreLibraries.gmk Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/make/lib/CoreLibraries.gmk Thu Jan 14 20:57:33 2016 -0800
@@ -25,6 +25,10 @@
WIN_VERIFY_LIB := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libverify/verify.lib
+# Hook to include the corresponding custom file, if present.
+$(eval $(call IncludeCustomExtension, jdk, lib/CoreLibraries.gmk))
+
+
##########################################################################################
# libfdlibm is statically linked with libjava below and not delivered into the
# product on its own.
@@ -119,6 +123,9 @@
-I$(SUPPORT_OUTPUTDIR)/headers/java.base \
-DARCHPROPNAME='"$(OPENJDK_TARGET_CPU_OSARCH)"'
+# Make it possible to override this variable
+LIBJAVA_MAPFILE ?= $(JDK_TOPDIR)/make/mapfiles/libjava/mapfile-vers
+
ifeq ($(OPENJDK_TARGET_OS), macosx)
BUILD_LIBJAVA_java_props_md.c_CFLAGS := -x objective-c
BUILD_LIBJAVA_java_props_macosx.c_CFLAGS := -x objective-c
@@ -146,7 +153,7 @@
System.c_CFLAGS := $(VERSION_CFLAGS), \
jdk_util.c_CFLAGS := $(VERSION_CFLAGS), \
DISABLED_WARNINGS_solstudio := E_STATEMENT_NOT_REACHED, \
- MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjava/mapfile-vers, \
+ MAPFILE := $(LIBJAVA_MAPFILE), \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LDFLAGS_macosx := -L$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/, \
--- a/jdk/make/lib/LibCommon.gmk Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/make/lib/LibCommon.gmk Thu Jan 14 20:57:33 2016 -0800
@@ -27,6 +27,11 @@
include MakeBase.gmk
include NativeCompilation.gmk
+# Hook to include the corresponding custom file, if present.
+$(eval $(call IncludeCustomExtension, jdk, lib/LibCommon.gmk))
+
+################################################################################
+
GLOBAL_VERSION_INFO_RESOURCE := $(JDK_TOPDIR)/src/java.base/windows/native/common/version.rc
# Absolute paths to lib files on windows for use in LDFLAGS. Should figure out a more
@@ -56,7 +61,7 @@
# Find the default set of src dirs for a native library.
# Param 1 - module name
# Param 2 - library name
-FindSrcDirsForLib = \
+FindSrcDirsForLib += \
$(call uniq, $(wildcard \
$(JDK_TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS)/native/lib$(strip $2) \
$(JDK_TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS_TYPE)/native/lib$(strip $2) \
--- a/jdk/make/src/classes/build/tools/spp/Spp.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/make/src/classes/build/tools/spp/Spp.java Thu Jan 14 20:57:33 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -32,9 +32,10 @@
* Spp: A simple regex-based stream preprocessor based on Mark Reinhold's
* sed-based spp.sh
*
- * Usage: java build.tools.spp.Spp [-be] [-Kkey] -Dvar=value ... <in >out
+ * Usage: java build.tools.spp.Spp [-be] [-nel] [-Kkey] -Dvar=value ... <in >out
*
- * Source-file constructs
+ * If -nel is declared then empty lines will not be substituted for lines of
+ * text in the template that do not appear in the output.
*
* Meaningful only at beginning of line, works with any number of keys:
*
@@ -64,9 +65,10 @@
public class Spp {
public static void main(String args[]) throws Exception {
- Map<String, String> vars = new HashMap<String, String>();
- Set<String> keys = new HashSet<String>();
+ Map<String, String> vars = new HashMap<>();
+ Set<String> keys = new HashSet<>();
boolean be = false;
+ boolean el = true;
for (String arg:args) {
if (arg.startsWith("-D")) {
@@ -76,8 +78,10 @@
keys.add(arg.substring(2));
} else if ("-be".equals(arg)) {
be = true;
+ } else if ("-nel".equals(arg)) {
+ el = false;
} else {
- System.err.println("Usage: java build.tools.spp.Spp [-be] [-Kkey] -Dvar=value ... <in >out");
+ System.err.println("Usage: java build.tools.spp.Spp [-be] [-nel] [-Kkey] -Dvar=value ... <in >out");
System.exit(-1);
}
}
@@ -85,7 +89,7 @@
StringBuffer out = new StringBuffer();
new Spp().spp(new Scanner(System.in),
out, "",
- keys, vars, be,
+ keys, vars, be, el,
false);
System.out.print(out.toString());
}
@@ -93,7 +97,7 @@
static final String LNSEP = System.getProperty("line.separator");
static final String KEY = "([a-zA-Z0-9]+)";
static final String VAR = "([a-zA-Z0-9_\\-]+)";
- static final String TEXT = "([a-zA-Z0-9&;,.<>/#() \\$]+)"; // $ -- hack embedded $var$
+ static final String TEXT = "([a-zA-Z0-9&;,.<>/#() \\?\\[\\]\\$]+)"; // $ -- hack embedded $var$
static final int GN_NOT = 1;
static final int GN_KEY = 2;
@@ -101,11 +105,11 @@
static final int GN_NO = 5;
static final int GN_VAR = 6;
- Matcher ifkey = Pattern.compile("^#if\\[(!)?" + KEY + "\\]").matcher("");
- Matcher elsekey = Pattern.compile("^#else\\[(!)?" + KEY + "\\]").matcher("");
- Matcher endkey = Pattern.compile("^#end\\[(!)?" + KEY + "\\]").matcher("");
- Matcher vardef = Pattern.compile("\\{#if\\[(!)?" + KEY + "\\]\\?" + TEXT + "(:"+ TEXT + ")?\\}|\\$" + VAR + "\\$").matcher("");
- Matcher vardef2 = Pattern.compile("\\$" + VAR + "\\$").matcher("");
+ final Matcher ifkey = Pattern.compile("^#if\\[(!)?" + KEY + "\\]").matcher("");
+ final Matcher elsekey = Pattern.compile("^#else\\[(!)?" + KEY + "\\]").matcher("");
+ final Matcher endkey = Pattern.compile("^#end\\[(!)?" + KEY + "\\]").matcher("");
+ final Matcher vardef = Pattern.compile("\\{#if\\[(!)?" + KEY + "\\]\\?" + TEXT + "(:"+ TEXT + ")?\\}|\\$" + VAR + "\\$").matcher("");
+ final Matcher vardef2 = Pattern.compile("\\$" + VAR + "\\$").matcher("");
void append(StringBuffer buf, String ln,
Set<String> keys, Map<String, String> vars) {
@@ -135,7 +139,7 @@
// return true if #end[key], #end or EOF reached
boolean spp(Scanner in, StringBuffer buf, String key,
Set<String> keys, Map<String, String> vars,
- boolean be, boolean skip) {
+ boolean be, boolean el, boolean skip) {
while (in.hasNextLine()) {
String ln = in.nextLine();
if (be) {
@@ -154,9 +158,9 @@
boolean test = keys.contains(k);
if (ifkey.group(GN_NOT) != null)
test = !test;
- buf.append(LNSEP);
- if (!spp(in, buf, k, keys, vars, be, skip || !test)) {
- spp(in, buf, k, keys, vars, be, skip || test);
+ if (el) buf.append(LNSEP);
+ if (!spp(in, buf, k, keys, vars, be, el, skip || !test)) {
+ spp(in, buf, k, keys, vars, be, el, skip || test);
}
continue;
}
@@ -164,14 +168,14 @@
if (!key.equals(elsekey.group(GN_KEY))) {
throw new Error("Mis-matched #if-else-end at line <" + ln + ">");
}
- buf.append(LNSEP);
+ if (el) buf.append(LNSEP);
return false;
}
if (endkey.reset(ln).find()) {
if (!key.equals(endkey.group(GN_KEY))) {
throw new Error("Mis-matched #if-else-end at line <" + ln + ">");
}
- buf.append(LNSEP);
+ if (el) buf.append(LNSEP);
return true;
}
if (ln.startsWith("#warn")) {
@@ -181,8 +185,9 @@
}
if (!skip) {
append(buf, ln, keys, vars);
+ if (!el) buf.append(LNSEP);
}
- buf.append(LNSEP);
+ if (el) buf.append(LNSEP);
}
return true;
}
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/CounterMode.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/CounterMode.java Thu Jan 14 20:57:33 2016 -0800
@@ -26,7 +26,9 @@
package com.sun.crypto.provider;
import java.security.InvalidKeyException;
+import java.util.Objects;
+import jdk.internal.HotSpotIntrinsicCandidate;
/**
* This class represents ciphers in counter (CTR) mode.
@@ -138,7 +140,7 @@
* <code>cipherOffset</code>.
*
* @param in the buffer with the input data to be encrypted
- * @param inOffset the offset in <code>plain</code>
+ * @param inOff the offset in <code>plain</code>
* @param len the length of the input data
* @param out the buffer for the result
* @param outOff the offset in <code>cipher</code>
@@ -170,6 +172,15 @@
* are encrypted on demand.
*/
private int crypt(byte[] in, int inOff, int len, byte[] out, int outOff) {
+
+ cryptBlockCheck(in, inOff, len);
+ cryptBlockCheck(out, outOff, len);
+ return implCrypt(in, inOff, len, out, outOff);
+ }
+
+ // Implementation of crpyt() method. Possibly replaced with a compiler intrinsic.
+ @HotSpotIntrinsicCandidate
+ private int implCrypt(byte[] in, int inOff, int len, byte[] out, int outOff) {
int result = len;
while (len-- > 0) {
if (used >= blockSize) {
@@ -181,4 +192,23 @@
}
return result;
}
+
+ // Used to perform all checks required by the Java semantics
+ // (i.e., null checks and bounds checks) on the input parameters to crypt().
+ // Normally, the Java Runtime performs these checks, however, as crypt() is
+ // possibly replaced with compiler intrinsic, the JDK performs the
+ // required checks instead.
+ // Does not check accesses to class-internal (private) arrays.
+ private static void cryptBlockCheck(byte[] array, int offset, int len) {
+ Objects.requireNonNull(array);
+
+ if (offset < 0 || len < 0 || offset >= array.length) {
+ throw new ArrayIndexOutOfBoundsException(offset);
+ }
+
+ int largestIndex = offset + len - 1;
+ if (largestIndex < 0 || largestIndex >= array.length) {
+ throw new ArrayIndexOutOfBoundsException(largestIndex);
+ }
+ }
}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java Thu Jan 14 20:57:33 2016 -0800
@@ -25,25 +25,25 @@
package java.lang.invoke;
-import static jdk.internal.org.objectweb.asm.Opcodes.*;
-import static java.lang.invoke.LambdaForm.*;
-import static java.lang.invoke.LambdaForm.BasicType.*;
-import static java.lang.invoke.MethodHandleStatics.*;
+import jdk.internal.vm.annotation.Stable;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.FieldVisitor;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import sun.invoke.util.ValueConversions;
+import sun.invoke.util.Wrapper;
import java.lang.invoke.LambdaForm.NamedFunction;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Field;
import java.util.Arrays;
-import java.util.function.Function;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
-import jdk.internal.org.objectweb.asm.FieldVisitor;
-import sun.invoke.util.ValueConversions;
-import sun.invoke.util.Wrapper;
-
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.MethodVisitor;
+import static java.lang.invoke.LambdaForm.BasicType;
+import static java.lang.invoke.LambdaForm.BasicType.*;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
/**
* The flavor of method handle which emulates an invoke instruction
@@ -459,7 +459,7 @@
static final String BMH_SIG = "L"+BMH+";";
static final String SPECIES_DATA = "java/lang/invoke/BoundMethodHandle$SpeciesData";
static final String SPECIES_DATA_SIG = "L"+SPECIES_DATA+";";
- static final String STABLE_SIG = "Ljava/lang/invoke/Stable;";
+ static final String STABLE_SIG = "Ljdk/internal/vm/annotation/Stable;";
static final String SPECIES_PREFIX_NAME = "Species_";
static final String SPECIES_PREFIX_PATH = BMH + "$" + SPECIES_PREFIX_NAME;
--- a/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java Thu Jan 14 20:57:33 2016 -0800
@@ -26,19 +26,23 @@
package java.lang.invoke;
import jdk.internal.misc.Unsafe;
+import jdk.internal.vm.annotation.ForceInline;
+import sun.invoke.util.ValueConversions;
+import sun.invoke.util.VerifyAccess;
+import sun.invoke.util.VerifyType;
+import sun.invoke.util.Wrapper;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
-import sun.invoke.util.VerifyAccess;
+import java.util.Objects;
+
+import static java.lang.invoke.LambdaForm.*;
import static java.lang.invoke.MethodHandleNatives.Constants.*;
-import static java.lang.invoke.LambdaForm.*;
+import static java.lang.invoke.MethodHandleStatics.UNSAFE;
+import static java.lang.invoke.MethodHandleStatics.newInternalError;
import static java.lang.invoke.MethodTypeForm.*;
-import static java.lang.invoke.MethodHandleStatics.*;
-import java.lang.ref.WeakReference;
-import java.lang.reflect.Field;
-import java.util.Objects;
-import sun.invoke.util.ValueConversions;
-import sun.invoke.util.VerifyType;
-import sun.invoke.util.Wrapper;
/**
* The flavor of method handle which implements a constant reference
--- a/jdk/src/java.base/share/classes/java/lang/invoke/DontInline.java Thu Jan 14 12:04:19 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 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 java.lang.invoke;
-
-import java.lang.annotation.*;
-
-/**
- * Internal marker for some methods in the JSR 292 implementation.
- */
-/*non-public*/
-@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
-@Retention(RetentionPolicy.RUNTIME)
-@interface DontInline {
-}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/ForceInline.java Thu Jan 14 12:04:19 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 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 java.lang.invoke;
-
-import java.lang.annotation.*;
-
-/**
- * Internal marker for some methods in the JSR 292 implementation.
- */
-/*non-public*/
-@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
-@Retention(RetentionPolicy.RUNTIME)
-@interface ForceInline {
-}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Thu Jan 14 20:57:33 2016 -0800
@@ -625,9 +625,9 @@
if (lambdaForm.forceInline) {
// Force inlining of this invoker method.
- mv.visitAnnotation("Ljava/lang/invoke/ForceInline;", true);
+ mv.visitAnnotation("Ljdk/internal/vm/annotation/ForceInline;", true);
} else {
- mv.visitAnnotation("Ljava/lang/invoke/DontInline;", true);
+ mv.visitAnnotation("Ljdk/internal/vm/annotation/DontInline;", true);
}
if (lambdaForm.customized != null) {
@@ -1309,7 +1309,7 @@
mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
// Don't inline the interpreter entry.
- mv.visitAnnotation("Ljava/lang/invoke/DontInline;", true);
+ mv.visitAnnotation("Ljdk/internal/vm/annotation/DontInline;", true);
// create parameter array
emitIconstInsn(invokerType.parameterCount());
@@ -1368,7 +1368,7 @@
mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
// Force inlining of this invoker method.
- mv.visitAnnotation("Ljava/lang/invoke/ForceInline;", true);
+ mv.visitAnnotation("Ljdk/internal/vm/annotation/ForceInline;", true);
// Load receiver
emitAloadInsn(0);
--- a/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java Thu Jan 14 20:57:33 2016 -0800
@@ -25,6 +25,10 @@
package java.lang.invoke;
+import jdk.internal.vm.annotation.DontInline;
+import jdk.internal.vm.annotation.ForceInline;
+import jdk.internal.vm.annotation.Stable;
+
import java.lang.reflect.Array;
import java.util.Arrays;
--- a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java Thu Jan 14 20:57:33 2016 -0800
@@ -25,18 +25,24 @@
package java.lang.invoke;
-import java.lang.annotation.*;
+import jdk.internal.vm.annotation.DontInline;
+import jdk.internal.vm.annotation.Stable;
+import sun.invoke.util.Wrapper;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Field;
import java.lang.reflect.Method;
-import java.util.List;
import java.util.Arrays;
import java.util.HashMap;
-
-import sun.invoke.util.Wrapper;
-import java.lang.reflect.Field;
+import java.util.List;
import static java.lang.invoke.LambdaForm.BasicType.*;
-import static java.lang.invoke.MethodHandleStatics.*;
-import static java.lang.invoke.MethodHandleNatives.Constants.*;
+import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
+import static java.lang.invoke.MethodHandleStatics.debugEnabled;
+import static java.lang.invoke.MethodHandleStatics.newInternalError;
/**
* The symbolic, non-executable form of a method handle's invocation semantics.
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Thu Jan 14 20:57:33 2016 -0800
@@ -33,6 +33,7 @@
import java.util.List;
import java.util.function.Function;
+import jdk.internal.vm.annotation.Stable;
import sun.invoke.empty.Empty;
import sun.invoke.util.ValueConversions;
import sun.invoke.util.VerifyType;
@@ -1487,7 +1488,7 @@
}
private static final int LEFT_ARGS = FILL_ARRAYS_COUNT - 1;
- private static final @Stable MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY+1];
+ private static final @Stable MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY + 1];
/** fill_array_to_right(N).invoke(a, argL..arg[N-1])
* fills a[L]..a[N-1] with corresponding arguments,
* and then returns a. The value L is a global constant (LEFT_ARGS).
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java Thu Jan 14 20:57:33 2016 -0800
@@ -25,6 +25,7 @@
package java.lang.invoke;
+import jdk.internal.vm.annotation.Stable;
import sun.invoke.util.Wrapper;
import java.lang.ref.WeakReference;
import java.lang.ref.Reference;
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java Thu Jan 14 20:57:33 2016 -0800
@@ -25,6 +25,7 @@
package java.lang.invoke;
+import jdk.internal.vm.annotation.Stable;
import sun.invoke.util.Wrapper;
import java.lang.ref.SoftReference;
import static java.lang.invoke.MethodHandleStatics.*;
--- a/jdk/src/java.base/share/classes/java/lang/invoke/Stable.java Thu Jan 14 12:04:19 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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 java.lang.invoke;
-
-import java.lang.annotation.*;
-
-/**
- * A field may be annotated as stable if all of its component variables
- * changes value at most once.
- * A field's value counts as its component value.
- * If the field is typed as an array, then all the non-null components
- * of the array, of depth up to the rank of the field's array type,
- * also count as component values.
- * By extension, any variable (either array or field) which has annotated
- * as stable is called a stable variable, and its non-null or non-zero
- * value is called a stable value.
- * <p>
- * Since all fields begin with a default value of null for references
- * (resp., zero for primitives), it follows that this annotation indicates
- * that the first non-null (resp., non-zero) value stored in the field
- * will never be changed.
- * <p>
- * If the field is not of an array type, there are no array elements,
- * then the value indicated as stable is simply the value of the field.
- * If the dynamic type of the field value is an array but the static type
- * is not, the components of the array are <em>not</em> regarded as stable.
- * <p>
- * If the field is an array type, then both the field value and
- * all the components of the field value (if the field value is non-null)
- * are indicated to be stable.
- * If the field type is an array type with rank {@code N > 1},
- * then each component of the field value (if the field value is non-null),
- * is regarded as a stable array of rank {@code N-1}.
- * <p>
- * Fields which are declared {@code final} may also be annotated as stable.
- * Since final fields already behave as stable values, such an annotation
- * indicates no additional information, unless the type of the field is
- * an array type.
- * <p>
- * It is (currently) undefined what happens if a field annotated as stable
- * is given a third value. In practice, if the JVM relies on this annotation
- * to promote a field reference to a constant, it may be that the Java memory
- * model would appear to be broken, if such a constant (the second value of the field)
- * is used as the value of the field even after the field value has changed.
- */
-/* package-private */
-@Target(ElementType.FIELD)
-@Retention(RetentionPolicy.RUNTIME)
-@interface Stable {
-}
--- a/jdk/src/java.base/share/classes/java/lang/ref/PhantomReference.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/ref/PhantomReference.java Thu Jan 14 20:57:33 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -29,23 +29,20 @@
/**
* Phantom reference objects, which are enqueued after the collector
* determines that their referents may otherwise be reclaimed. Phantom
- * references are most often used for scheduling pre-mortem cleanup actions in
- * a more flexible way than is possible with the Java finalization mechanism.
+ * references are most often used to schedule post-mortem cleanup actions.
*
- * <p> If the garbage collector determines at a certain point in time that the
- * referent of a phantom reference is <a
- * href="package-summary.html#reachability">phantom reachable</a>, then at that
- * time or at some later time it will enqueue the reference.
+ * <p> Suppose the garbage collector determines at a certain point in time
+ * that an object is <a href="package-summary.html#reachability">
+ * phantom reachable</a>. At that time it will atomically clear
+ * all phantom references to that object and all phantom references to
+ * any other phantom-reachable objects from which that object is reachable.
+ * At the same time or at some later time it will enqueue those newly-cleared
+ * phantom references that are registered with reference queues.
*
* <p> In order to ensure that a reclaimable object remains so, the referent of
* a phantom reference may not be retrieved: The {@code get} method of a
* phantom reference always returns {@code null}.
*
- * <p> Unlike soft and weak references, phantom references are not
- * automatically cleared by the garbage collector as they are enqueued. An
- * object that is reachable via phantom references will remain so until all
- * such references are cleared or themselves become unreachable.
- *
* @author Mark Reinhold
* @since 1.2
*/
@@ -69,8 +66,8 @@
*
* <p> It is possible to create a phantom reference with a {@code null}
* queue, but such a reference is completely useless: Its {@code get}
- * method will always return null and, since it does not have a queue, it
- * will never be enqueued.
+ * method will always return {@code null} and, since it does not have a queue,
+ * it will never be enqueued.
*
* @param referent the object the new phantom reference will refer to
* @param q the queue with which the reference is to be registered,
--- a/jdk/src/java.base/share/classes/java/lang/ref/Reference.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/ref/Reference.java Thu Jan 14 20:57:33 2016 -0800
@@ -25,6 +25,7 @@
package java.lang.ref;
+import jdk.internal.vm.annotation.DontInline;
import sun.misc.Cleaner;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.misc.JavaLangRefAccess;
@@ -310,4 +311,120 @@
this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
}
+ /**
+ * Ensures that the object referenced by the given reference remains
+ * <a href="package-summary.html#reachability"><em>strongly reachable</em></a>,
+ * regardless of any prior actions of the program that might otherwise cause
+ * the object to become unreachable; thus, the referenced object is not
+ * reclaimable by garbage collection at least until after the invocation of
+ * this method. Invocation of this method does not itself initiate garbage
+ * collection or finalization.
+ *
+ * <p> This method establishes an ordering for
+ * <a href="package-summary.html#reachability"><em>strong reachability</em></a>
+ * with respect to garbage collection. It controls relations that are
+ * otherwise only implicit in a program -- the reachability conditions
+ * triggering garbage collection. This method is designed for use in
+ * uncommon situations of premature finalization where using
+ * {@code synchronized} blocks or methods, or using other synchronization
+ * facilities are not possible or do not provide the desired control. This
+ * method is applicable only when reclamation may have visible effects,
+ * which is possible for objects with finalizers (See
+ * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.6">
+ * Section 12.6 17 of <cite>The Java™ Language Specification</cite></a>)
+ * that are implemented in ways that rely on ordering control for correctness.
+ *
+ * @apiNote
+ * Finalization may occur whenever the virtual machine detects that no
+ * reference to an object will ever be stored in the heap: The garbage
+ * collector may reclaim an object even if the fields of that object are
+ * still in use, so long as the object has otherwise become unreachable.
+ * This may have surprising and undesirable effects in cases such as the
+ * following example in which the bookkeeping associated with a class is
+ * managed through array indices. Here, method {@code action} uses a
+ * {@code reachabilityFence} to ensure that the {@code Resource} object is
+ * not reclaimed before bookkeeping on an associated
+ * {@code ExternalResource} has been performed; in particular here, to
+ * ensure that the array slot holding the {@code ExternalResource} is not
+ * nulled out in method {@link Object#finalize}, which may otherwise run
+ * concurrently.
+ *
+ * <pre> {@code
+ * class Resource {
+ * private static ExternalResource[] externalResourceArray = ...
+ *
+ * int myIndex;
+ * Resource(...) {
+ * myIndex = ...
+ * externalResourceArray[myIndex] = ...;
+ * ...
+ * }
+ * protected void finalize() {
+ * externalResourceArray[myIndex] = null;
+ * ...
+ * }
+ * public void action() {
+ * try {
+ * // ...
+ * int i = myIndex;
+ * Resource.update(externalResourceArray[i]);
+ * } finally {
+ * Reference.reachabilityFence(this);
+ * }
+ * }
+ * private static void update(ExternalResource ext) {
+ * ext.status = ...;
+ * }
+ * }}</pre>
+ *
+ * Here, the invocation of {@code reachabilityFence} is nonintuitively
+ * placed <em>after</em> the call to {@code update}, to ensure that the
+ * array slot is not nulled out by {@link Object#finalize} before the
+ * update, even if the call to {@code action} was the last use of this
+ * object. This might be the case if, for example a usage in a user program
+ * had the form {@code new Resource().action();} which retains no other
+ * reference to this {@code Resource}. While probably overkill here,
+ * {@code reachabilityFence} is placed in a {@code finally} block to ensure
+ * that it is invoked across all paths in the method. In a method with more
+ * complex control paths, you might need further precautions to ensure that
+ * {@code reachabilityFence} is encountered along all of them.
+ *
+ * <p> It is sometimes possible to better encapsulate use of
+ * {@code reachabilityFence}. Continuing the above example, if it were
+ * acceptable for the call to method {@code update} to proceed even if the
+ * finalizer had already executed (nulling out slot), then you could
+ * localize use of {@code reachabilityFence}:
+ *
+ * <pre> {@code
+ * public void action2() {
+ * // ...
+ * Resource.update(getExternalResource());
+ * }
+ * private ExternalResource getExternalResource() {
+ * ExternalResource ext = externalResourceArray[myIndex];
+ * Reference.reachabilityFence(this);
+ * return ext;
+ * }}</pre>
+ *
+ * <p> Method {@code reachabilityFence} is not required in constructions
+ * that themselves ensure reachability. For example, because objects that
+ * are locked cannot, in general, be reclaimed, it would suffice if all
+ * accesses of the object, in all methods of class {@code Resource}
+ * (including {@code finalize}) were enclosed in {@code synchronized (this)}
+ * blocks. (Further, such blocks must not include infinite loops, or
+ * themselves be unreachable, which fall into the corner case exceptions to
+ * the "in general" disclaimer.) However, method {@code reachabilityFence}
+ * remains a better option in cases where this approach is not as efficient,
+ * desirable, or possible; for example because it would encounter deadlock.
+ *
+ * @param ref the reference. If {@code null}, this method has no effect.
+ * @since 9
+ */
+ @DontInline
+ public static void reachabilityFence(Object ref) {
+ // Does nothing, because this method is annotated with @DontInline
+ // HotSpot needs to retain the ref and not GC it before a call to this
+ // method
+ }
+
}
--- a/jdk/src/java.base/share/classes/java/lang/ref/package-info.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/ref/package-info.java Thu Jan 14 20:57:33 2016 -0800
@@ -66,9 +66,9 @@
* object with a <em>reference queue</em> at the time the reference
* object is created. Some time after the garbage collector
* determines that the reachability of the referent has changed to the
- * value corresponding to the type of the reference, it will add the
- * reference to the associated queue. At this point, the reference is
- * considered to be <em>enqueued</em>. The program may remove
+ * value corresponding to the type of the reference, it will clear the
+ * reference and add it to the associated queue. At this point, the
+ * reference is considered to be <em>enqueued</em>. The program may remove
* references from a queue either by polling or by blocking until a
* reference becomes available. Reference queues are implemented by
* the {@link java.lang.ref.ReferenceQueue} class.
@@ -94,16 +94,6 @@
* structure, this check will add little overhead to the hashtable
* access methods.
*
- * <h3>Automatically-cleared references</h3>
- *
- * Soft and weak references are automatically cleared by the collector
- * before being added to the queues with which they are registered, if
- * any. Therefore soft and weak references need not be registered
- * with a queue in order to be useful, while phantom references do.
- * An object that is reachable via phantom references will remain so
- * until all such references are cleared or themselves become
- * unreachable.
- *
* <a name="reachability"></a>
* <h3>Reachability</h3>
*
--- a/jdk/src/java.base/share/classes/java/util/Arrays.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/util/Arrays.java Thu Jan 14 20:57:33 2016 -0800
@@ -110,7 +110,7 @@
* Checks that {@code fromIndex} and {@code toIndex} are in
* the range and throws an exception if they aren't.
*/
- private static void rangeCheck(int arrayLength, int fromIndex, int toIndex) {
+ static void rangeCheck(int arrayLength, int fromIndex, int toIndex) {
if (fromIndex > toIndex) {
throw new IllegalArgumentException(
"fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
@@ -2579,11 +2579,7 @@
if (a2.length != length)
return false;
- for (int i=0; i<length; i++)
- if (a[i] != a2[i])
- return false;
-
- return true;
+ return ArraysSupport.mismatch(a, a2, length) < 0;
}
/**
@@ -2628,11 +2624,9 @@
if (aLength != bLength)
return false;
- for (int i = 0; i < aLength; i++)
- if (a[aFromIndex++] != b[bFromIndex++])
- return false;
-
- return true;
+ return ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ aLength) < 0;
}
/**
@@ -2657,11 +2651,7 @@
if (a2.length != length)
return false;
- for (int i=0; i<length; i++)
- if (a[i] != a2[i])
- return false;
-
- return true;
+ return ArraysSupport.mismatch(a, a2, length) < 0;
}
/**
@@ -2706,11 +2696,9 @@
if (aLength != bLength)
return false;
- for (int i = 0; i < aLength; i++)
- if (a[aFromIndex++] != b[bFromIndex++])
- return false;
-
- return true;
+ return ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ aLength) < 0;
}
/**
@@ -2735,11 +2723,7 @@
if (a2.length != length)
return false;
- for (int i=0; i<length; i++)
- if (a[i] != a2[i])
- return false;
-
- return true;
+ return ArraysSupport.mismatch(a, a2, length) < 0;
}
/**
@@ -2784,11 +2768,9 @@
if (aLength != bLength)
return false;
- for (int i = 0; i < aLength; i++)
- if (a[aFromIndex++] != b[bFromIndex++])
- return false;
-
- return true;
+ return ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ aLength) < 0;
}
/**
@@ -2814,11 +2796,7 @@
if (a2.length != length)
return false;
- for (int i=0; i<length; i++)
- if (a[i] != a2[i])
- return false;
-
- return true;
+ return ArraysSupport.mismatch(a, a2, length) < 0;
}
/**
@@ -2863,11 +2841,9 @@
if (aLength != bLength)
return false;
- for (int i = 0; i < aLength; i++)
- if (a[aFromIndex++] != b[bFromIndex++])
- return false;
-
- return true;
+ return ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ aLength) < 0;
}
/**
@@ -2893,11 +2869,7 @@
if (a2.length != length)
return false;
- for (int i=0; i<length; i++)
- if (a[i] != a2[i])
- return false;
-
- return true;
+ return ArraysSupport.mismatch(a, a2, length) < 0;
}
/**
@@ -2942,11 +2914,9 @@
if (aLength != bLength)
return false;
- for (int i = 0; i < aLength; i++)
- if (a[aFromIndex++] != b[bFromIndex++])
- return false;
-
- return true;
+ return ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ aLength) < 0;
}
/**
@@ -2971,11 +2941,7 @@
if (a2.length != length)
return false;
- for (int i=0; i<length; i++)
- if (a[i] != a2[i])
- return false;
-
- return true;
+ return ArraysSupport.mismatch(a, a2, length) < 0;
}
/**
@@ -3020,11 +2986,9 @@
if (aLength != bLength)
return false;
- for (int i = 0; i < aLength; i++)
- if (a[aFromIndex++] != b[bFromIndex++])
- return false;
-
- return true;
+ return ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ aLength) < 0;
}
/**
@@ -3055,14 +3019,7 @@
if (a2.length != length)
return false;
- for (int i=0; i<length; i++) {
- double v1 = a[i], v2 = a2[i];
- if (Double.doubleToRawLongBits(v1) != Double.doubleToRawLongBits(v2))
- if (!Double.isNaN(v1) || !Double.isNaN(v2))
- return false;
- }
-
- return true;
+ return ArraysSupport.mismatch(a, a2, length) < 0;
}
/**
@@ -3113,14 +3070,8 @@
if (aLength != bLength)
return false;
- for (int i = 0; i < aLength; i++) {
- Double va = a[aFromIndex++], vb = b[bFromIndex++];
- if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb))
- if (!Double.isNaN(va) || !Double.isNaN(vb))
- return false;
- }
-
- return true;
+ return ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex, aLength) < 0;
}
/**
@@ -3151,14 +3102,7 @@
if (a2.length != length)
return false;
- for (int i=0; i<length; i++) {
- float v1 = a[i], v2 = a2[i];
- if (Float.floatToRawIntBits(v1) != Float.floatToRawIntBits(v2))
- if (!Float.isNaN(v1) || !Float.isNaN(v2))
- return false;
- }
-
- return true;
+ return ArraysSupport.mismatch(a, a2, length) < 0;
}
/**
@@ -3209,14 +3153,8 @@
if (aLength != bLength)
return false;
- for (int i = 0; i < aLength; i++) {
- float va = a[aFromIndex++], vb = b[bFromIndex++];
- if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb))
- if (!Float.isNaN(va) || !Float.isNaN(vb))
- return false;
- }
-
- return true;
+ return ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex, aLength) < 0;
}
/**
@@ -5804,9 +5742,10 @@
if (a == null || b == null)
return a == null ? -1 : 1;
- int length = Math.min(a.length, b.length);
- for (int i = 0; i < length; i++) {
- if (a[i] != b[i]) return Boolean.compare(a[i], b[i]);
+ int i = ArraysSupport.mismatch(a, b,
+ Math.min(a.length, b.length));
+ if (i >= 0) {
+ return Boolean.compare(a[i], b[i]);
}
return a.length - b.length;
@@ -5880,11 +5819,11 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
- int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- boolean va = a[aFromIndex++];
- boolean vb = b[bFromIndex++];
- if (va != vb) return Boolean.compare(va, vb);
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ Math.min(aLength, bLength));
+ if (i >= 0) {
+ return Boolean.compare(a[aFromIndex + i], b[bFromIndex + i]);
}
return aLength - bLength;
@@ -5939,9 +5878,10 @@
if (a == null || b == null)
return a == null ? -1 : 1;
- int length = Math.min(a.length, b.length);
- for (int i = 0; i < length; i++) {
- if (a[i] != b[i]) return Byte.compare(a[i], b[i]);
+ int i = ArraysSupport.mismatch(a, b,
+ Math.min(a.length, b.length));
+ if (i >= 0) {
+ return Byte.compare(a[i], b[i]);
}
return a.length - b.length;
@@ -6014,11 +5954,11 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
- int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- byte va = a[aFromIndex++];
- byte vb = b[bFromIndex++];
- if (va != vb) return Byte.compare(va, vb);
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ Math.min(aLength, bLength));
+ if (i >= 0) {
+ return Byte.compare(a[aFromIndex + i], b[bFromIndex + i]);
}
return aLength - bLength;
@@ -6066,9 +6006,10 @@
if (a == null || b == null)
return a == null ? -1 : 1;
- int length = Math.min(a.length, b.length);
- for (int i = 0; i < length; i++) {
- if (a[i] != b[i]) return Byte.compareUnsigned(a[i], b[i]);
+ int i = ArraysSupport.mismatch(a, b,
+ Math.min(a.length, b.length));
+ if (i >= 0) {
+ return Byte.compareUnsigned(a[i], b[i]);
}
return a.length - b.length;
@@ -6133,11 +6074,11 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
- int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- byte va = a[aFromIndex++];
- byte vb = b[bFromIndex++];
- if (va != vb) return Byte.compareUnsigned(va, vb);
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ Math.min(aLength, bLength));
+ if (i >= 0) {
+ return Byte.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
}
return aLength - bLength;
@@ -6192,9 +6133,10 @@
if (a == null || b == null)
return a == null ? -1 : 1;
- int length = Math.min(a.length, b.length);
- for (int i = 0; i < length; i++) {
- if (a[i] != b[i]) return Short.compare(a[i], b[i]);
+ int i = ArraysSupport.mismatch(a, b,
+ Math.min(a.length, b.length));
+ if (i >= 0) {
+ return Short.compare(a[i], b[i]);
}
return a.length - b.length;
@@ -6267,11 +6209,11 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
- int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- short va = a[aFromIndex++];
- short vb = b[bFromIndex++];
- if (va != vb) return Short.compare(va, vb);
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ Math.min(aLength, bLength));
+ if (i >= 0) {
+ return Short.compare(a[aFromIndex + i], b[bFromIndex + i]);
}
return aLength - bLength;
@@ -6319,9 +6261,10 @@
if (a == null || b == null)
return a == null ? -1 : 1;
- int length = Math.min(a.length, b.length);
- for (int i = 0; i < length; i++) {
- if (a[i] != b[i]) return Short.compareUnsigned(a[i], b[i]);
+ int i = ArraysSupport.mismatch(a, b,
+ Math.min(a.length, b.length));
+ if (i >= 0) {
+ return Short.compareUnsigned(a[i], b[i]);
}
return a.length - b.length;
@@ -6385,11 +6328,11 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
- int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- short va = a[aFromIndex++];
- short vb = b[bFromIndex++];
- if (va != vb) return Short.compareUnsigned(va, vb);
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ Math.min(aLength, bLength));
+ if (i >= 0) {
+ return Short.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
}
return aLength - bLength;
@@ -6444,9 +6387,10 @@
if (a == null || b == null)
return a == null ? -1 : 1;
- int length = Math.min(a.length, b.length);
- for (int i = 0; i < length; i++) {
- if (a[i] != b[i]) return Character.compare(a[i], b[i]);
+ int i = ArraysSupport.mismatch(a, b,
+ Math.min(a.length, b.length));
+ if (i >= 0) {
+ return Character.compare(a[i], b[i]);
}
return a.length - b.length;
@@ -6519,11 +6463,11 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
- int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- char va = a[aFromIndex++];
- char vb = b[bFromIndex++];
- if (va != vb) return Character.compare(va, vb);
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ Math.min(aLength, bLength));
+ if (i >= 0) {
+ return Character.compare(a[aFromIndex + i], b[bFromIndex + i]);
}
return aLength - bLength;
@@ -6578,9 +6522,10 @@
if (a == null || b == null)
return a == null ? -1 : 1;
- int length = Math.min(a.length, b.length);
- for (int i = 0; i < length; i++) {
- if (a[i] != b[i]) return Integer.compare(a[i], b[i]);
+ int i = ArraysSupport.mismatch(a, b,
+ Math.min(a.length, b.length));
+ if (i >= 0) {
+ return Integer.compare(a[i], b[i]);
}
return a.length - b.length;
@@ -6653,11 +6598,11 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
- int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- int va = a[aFromIndex++];
- int vb = b[bFromIndex++];
- if (va != vb) return Integer.compare(va, vb);
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ Math.min(aLength, bLength));
+ if (i >= 0) {
+ return Integer.compare(a[aFromIndex + i], b[bFromIndex + i]);
}
return aLength - bLength;
@@ -6705,9 +6650,10 @@
if (a == null || b == null)
return a == null ? -1 : 1;
- int length = Math.min(a.length, b.length);
- for (int i = 0; i < length; i++) {
- if (a[i] != b[i]) return Integer.compareUnsigned(a[i], b[i]);
+ int i = ArraysSupport.mismatch(a, b,
+ Math.min(a.length, b.length));
+ if (i >= 0) {
+ return Integer.compareUnsigned(a[i], b[i]);
}
return a.length - b.length;
@@ -6771,11 +6717,11 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
- int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- int va = a[aFromIndex++];
- int vb = b[bFromIndex++];
- if (va != vb) return Integer.compareUnsigned(va, vb);
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ Math.min(aLength, bLength));
+ if (i >= 0) {
+ return Integer.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
}
return aLength - bLength;
@@ -6830,9 +6776,10 @@
if (a == null || b == null)
return a == null ? -1 : 1;
- int length = Math.min(a.length, b.length);
- for (int i = 0; i < length; i++) {
- if (a[i] != b[i]) return Long.compare(a[i], b[i]);
+ int i = ArraysSupport.mismatch(a, b,
+ Math.min(a.length, b.length));
+ if (i >= 0) {
+ return Long.compare(a[i], b[i]);
}
return a.length - b.length;
@@ -6905,11 +6852,11 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
- int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- long va = a[aFromIndex++];
- long vb = b[bFromIndex++];
- if (va != vb) return Long.compare(va, vb);
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ Math.min(aLength, bLength));
+ if (i >= 0) {
+ return Long.compare(a[aFromIndex + i], b[bFromIndex + i]);
}
return aLength - bLength;
@@ -6957,9 +6904,10 @@
if (a == null || b == null)
return a == null ? -1 : 1;
- int length = Math.min(a.length, b.length);
- for (int i = 0; i < length; i++) {
- if (a[i] != b[i]) return Long.compareUnsigned(a[i], b[i]);
+ int i = ArraysSupport.mismatch(a, b,
+ Math.min(a.length, b.length));
+ if (i >= 0) {
+ return Long.compareUnsigned(a[i], b[i]);
}
return a.length - b.length;
@@ -7023,11 +6971,11 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
- int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- long va = a[aFromIndex++];
- long vb = b[bFromIndex++];
- if (va != vb) return Long.compareUnsigned(va, vb);
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ Math.min(aLength, bLength));
+ if (i >= 0) {
+ return Long.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
}
return aLength - bLength;
@@ -7082,13 +7030,10 @@
if (a == null || b == null)
return a == null ? -1 : 1;
- int length = Math.min(a.length, b.length);
- for (int i = 0; i < length; i++) {
- float va = a[i], vb = b[i];
- if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb)) {
- int c = Float.compare(va, vb);
- if (c != 0) return c;
- }
+ int i = ArraysSupport.mismatch(a, b,
+ Math.min(a.length, b.length));
+ if (i >= 0) {
+ return Float.compare(a[i], b[i]);
}
return a.length - b.length;
@@ -7161,13 +7106,11 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
- int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- float va = a[aFromIndex++], vb = b[bFromIndex++];
- if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb)) {
- int c = Float.compare(va, vb);
- if (c != 0) return c;
- }
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ Math.min(aLength, bLength));
+ if (i >= 0) {
+ return Float.compare(a[aFromIndex + i], b[bFromIndex + i]);
}
return aLength - bLength;
@@ -7222,13 +7165,10 @@
if (a == null || b == null)
return a == null ? -1 : 1;
- int length = Math.min(a.length, b.length);
- for (int i = 0; i < length; i++) {
- double va = a[i], vb = b[i];
- if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb)) {
- int c = Double.compare(va, vb);
- if (c != 0) return c;
- }
+ int i = ArraysSupport.mismatch(a, b,
+ Math.min(a.length, b.length));
+ if (i >= 0) {
+ return Double.compare(a[i], b[i]);
}
return a.length - b.length;
@@ -7301,13 +7241,11 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
- int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- double va = a[aFromIndex++], vb = b[bFromIndex++];
- if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb)) {
- int c = Double.compare(va, vb);
- if (c != 0) return c;
- }
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ Math.min(aLength, bLength));
+ if (i >= 0) {
+ return Double.compare(a[aFromIndex + i], b[bFromIndex + i]);
}
return aLength - bLength;
@@ -7673,11 +7611,8 @@
if (a == b)
return -1;
- for (int i = 0; i < length; i++) {
- if (a[i] != b[i]) return i;
- }
-
- return a.length != b.length ? length : -1;
+ int i = ArraysSupport.mismatch(a, b, length);
+ return (i < 0 && a.length != b.length) ? length : i;
}
/**
@@ -7749,11 +7684,10 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- if (a[aFromIndex++] != b[bFromIndex++]) return i;
- }
-
- return aLength != bLength ? length : -1;
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ length);
+ return (i < 0 && aLength != bLength) ? length : i;
}
// Mismatch byte
@@ -7804,11 +7738,8 @@
if (a == b)
return -1;
- for (int i = 0; i < length; i++) {
- if (a[i] != b[i]) return i;
- }
-
- return a.length != b.length ? length : -1;
+ int i = ArraysSupport.mismatch(a, b, length);
+ return (i < 0 && a.length != b.length) ? length : i;
}
/**
@@ -7880,11 +7811,10 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- if (a[aFromIndex++] != b[bFromIndex++]) return i;
- }
-
- return aLength != bLength ? length : -1;
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ length);
+ return (i < 0 && aLength != bLength) ? length : i;
}
// Mismatch char
@@ -7935,11 +7865,8 @@
if (a == b)
return -1;
- for (int i = 0; i < length; i++) {
- if (a[i] != b[i]) return i;
- }
-
- return a.length != b.length ? length : -1;
+ int i = ArraysSupport.mismatch(a, b, length);
+ return (i < 0 && a.length != b.length) ? length : i;
}
/**
@@ -8011,11 +7938,10 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- if (a[aFromIndex++] != b[bFromIndex++]) return i;
- }
-
- return aLength != bLength ? length : -1;
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ length);
+ return (i < 0 && aLength != bLength) ? length : i;
}
// Mismatch short
@@ -8066,11 +7992,8 @@
if (a == b)
return -1;
- for (int i = 0; i < length; i++) {
- if (a[i] != b[i]) return i;
- }
-
- return a.length != b.length ? length : -1;
+ int i = ArraysSupport.mismatch(a, b, length);
+ return (i < 0 && a.length != b.length) ? length : i;
}
/**
@@ -8142,11 +8065,10 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- if (a[aFromIndex++] != b[bFromIndex++]) return i;
- }
-
- return aLength != bLength ? length : -1;
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ length);
+ return (i < 0 && aLength != bLength) ? length : i;
}
// Mismatch int
@@ -8197,11 +8119,8 @@
if (a == b)
return -1;
- for (int i = 0; i < length; i++) {
- if (a[i] != b[i]) return i;
- }
-
- return a.length != b.length ? length : -1;
+ int i = ArraysSupport.mismatch(a, b, length);
+ return (i < 0 && a.length != b.length) ? length : i;
}
/**
@@ -8273,11 +8192,10 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- if (a[aFromIndex++] != b[bFromIndex++]) return i;
- }
-
- return aLength != bLength ? length : -1;
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ length);
+ return (i < 0 && aLength != bLength) ? length : i;
}
// Mismatch long
@@ -8328,11 +8246,8 @@
if (a == b)
return -1;
- for (int i = 0; i < length; i++) {
- if (a[i] != b[i]) return i;
- }
-
- return a.length != b.length ? length : -1;
+ int i = ArraysSupport.mismatch(a, b, length);
+ return (i < 0 && a.length != b.length) ? length : i;
}
/**
@@ -8404,11 +8319,10 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- if (a[aFromIndex++] != b[bFromIndex++]) return i;
- }
-
- return aLength != bLength ? length : -1;
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ length);
+ return (i < 0 && aLength != bLength) ? length : i;
}
// Mismatch float
@@ -8459,14 +8373,8 @@
if (a == b)
return -1;
- for (int i = 0; i < length; i++) {
- float va = a[i], vb = b[i];
- if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb))
- if (!Float.isNaN(va) || !Float.isNaN(vb))
- return i;
- }
-
- return a.length != b.length ? length : -1;
+ int i = ArraysSupport.mismatch(a, b, length);
+ return (i < 0 && a.length != b.length) ? length : i;
}
/**
@@ -8538,14 +8446,10 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- float va = a[aFromIndex++], vb = b[bFromIndex++];
- if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb))
- if (!Float.isNaN(va) || !Float.isNaN(vb))
- return i;
- }
-
- return aLength != bLength ? length : -1;
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ length);
+ return (i < 0 && aLength != bLength) ? length : i;
}
// Mismatch double
@@ -8596,14 +8500,8 @@
if (a == b)
return -1;
- for (int i = 0; i < length; i++) {
- double va = a[i], vb = b[i];
- if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb))
- if (!Double.isNaN(va) || !Double.isNaN(vb))
- return i;
- }
-
- return a.length != b.length ? length : -1;
+ int i = ArraysSupport.mismatch(a, b, length);
+ return (i < 0 && a.length != b.length) ? length : i;
}
/**
@@ -8675,14 +8573,10 @@
int aLength = aToIndex - aFromIndex;
int bLength = bToIndex - bFromIndex;
int length = Math.min(aLength, bLength);
- for (int i = 0; i < length; i++) {
- double va = a[aFromIndex++], vb = b[bFromIndex++];
- if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb))
- if (!Double.isNaN(va) || !Double.isNaN(vb))
- return i;
- }
-
- return aLength != bLength ? length : -1;
+ int i = ArraysSupport.mismatch(a, aFromIndex,
+ b, bFromIndex,
+ length);
+ return (i < 0 && aLength != bLength) ? length : i;
}
// Mismatch objects
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/util/ArraysSupport.java Thu Jan 14 20:57:33 2016 -0800
@@ -0,0 +1,545 @@
+/*
+ * Copyright (c) 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.
+ */
+package java.util;
+
+import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.misc.Unsafe;
+
+/**
+ * Utility methods to find a mismatch between two primitive arrays.
+ *
+ * <p>Array equality and lexicographical comparison can be built on top of
+ * array mismatch functionality.
+ *
+ * <p>The mismatch method implementation, {@link #vectorizedMismatch}, leverages
+ * vector-based techniques to access and compare the contents of two arrays.
+ * The Java implementation uses {@code Unsafe.getLongUnaligned} to access the
+ * content of an array, thus access is supported on platforms that do not
+ * support unaligned access. For a byte[] array, 8 bytes (64 bits) can be
+ * accessed and compared as a unit rather than individually, which increases
+ * the performance when the method is compiled by the HotSpot VM. On supported
+ * platforms the mismatch implementation is intrinsified to leverage SIMD
+ * instructions. So for a byte[] array, 16 bytes (128 bits), 32 bytes
+ * (256 bits), and perhaps in the future even 64 bytes (512 bits), platform
+ * permitting, can be accessed and compared as a unit, which further increases
+ * the performance over the Java implementation.
+ *
+ * <p>None of the mismatch methods perform array bounds checks. It is the
+ * responsibility of the caller (direct or otherwise) to perform such checks
+ * before calling this method.
+ */
+class ArraysSupport {
+ static final Unsafe U = Unsafe.getUnsafe();
+
+ private static final boolean BIG_ENDIAN = U.isBigEndian();
+
+ private static final int LOG2_ARRAY_BOOLEAN_INDEX_SCALE = exactLog2(Unsafe.ARRAY_BOOLEAN_INDEX_SCALE);
+ private static final int LOG2_ARRAY_BYTE_INDEX_SCALE = exactLog2(Unsafe.ARRAY_BYTE_INDEX_SCALE);
+ private static final int LOG2_ARRAY_CHAR_INDEX_SCALE = exactLog2(Unsafe.ARRAY_CHAR_INDEX_SCALE);
+ private static final int LOG2_ARRAY_SHORT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_SHORT_INDEX_SCALE);
+ private static final int LOG2_ARRAY_INT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_INT_INDEX_SCALE);
+ private static final int LOG2_ARRAY_LONG_INDEX_SCALE = exactLog2(Unsafe.ARRAY_LONG_INDEX_SCALE);
+ private static final int LOG2_ARRAY_FLOAT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_FLOAT_INDEX_SCALE);
+ private static final int LOG2_ARRAY_DOUBLE_INDEX_SCALE = exactLog2(Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
+
+ private static final int LOG2_BYTE_BIT_SIZE = exactLog2(Byte.SIZE);
+
+ private static int exactLog2(int scale) {
+ if ((scale & (scale - 1)) != 0)
+ throw new Error("data type scale not a power of two");
+ return Integer.numberOfTrailingZeros(scale);
+ }
+
+ private ArraysSupport() {}
+
+ /**
+ * Find the relative index of the first mismatching pair of elements in two
+ * primitive arrays of the same component type. Pairs of elements will be
+ * tested in order relative to given offsets into both arrays.
+ *
+ * <p>This method does not perform type checks or bounds checks. It is the
+ * responsibility of the caller to perform such checks before calling this
+ * method.
+ *
+ * <p>The given offsets, in bytes, need not be aligned according to the
+ * given log<sub>2</sub> size the array elements. More specifically, an
+ * offset modulus the size need not be zero.
+ *
+ * @param a the first array to be tested for mismatch, or {@code null} for
+ * direct memory access
+ * @param aOffset the relative offset, in bytes, from the base address of
+ * the first array to test from, otherwise if the first array is
+ * {@code null}, an absolute address pointing to the first element to test.
+ * @param b the second array to be tested for mismatch, or {@code null} for
+ * direct memory access
+ * @param bOffset the relative offset, in bytes, from the base address of
+ * the second array to test from, otherwise if the second array is
+ * {@code null}, an absolute address pointing to the first element to test.
+ * @param length the number of array elements to test
+ * @param log2ArrayIndexScale log<sub>2</sub> of the array index scale, that
+ * corresponds to the size, in bytes, of an array element.
+ * @return if a mismatch is found a relative index, between 0 (inclusive)
+ * and {@code length} (exclusive), of the first mismatching pair of elements
+ * in the two arrays. Otherwise, if a mismatch is not found the bitwise
+ * compliment of the number of remaining pairs of elements to be checked in
+ * the tail of the two arrays.
+ */
+ @HotSpotIntrinsicCandidate
+ static int vectorizedMismatch(Object a, long aOffset,
+ Object b, long bOffset,
+ int length,
+ int log2ArrayIndexScale) {
+ // assert a.getClass().isArray();
+ // assert b.getClass().isArray();
+ // assert 0 <= length <= sizeOf(a)
+ // assert 0 <= length <= sizeOf(b)
+ // assert 0 <= log2ArrayIndexScale <= 3
+
+ int log2ValuesPerWidth = LOG2_ARRAY_LONG_INDEX_SCALE - log2ArrayIndexScale;
+ int wi = 0;
+ for (; wi < length >> log2ValuesPerWidth; wi++) {
+ long bi = ((long) wi) << LOG2_ARRAY_LONG_INDEX_SCALE;
+ long av = U.getLongUnaligned(a, aOffset + bi);
+ long bv = U.getLongUnaligned(b, bOffset + bi);
+ if (av != bv) {
+ long x = av ^ bv;
+ int o = BIG_ENDIAN
+ ? Long.numberOfLeadingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale)
+ : Long.numberOfTrailingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale);
+ return (wi << log2ValuesPerWidth) + o;
+ }
+ }
+
+ // Calculate the tail of remaining elements to check
+ int tail = length - (wi << log2ValuesPerWidth);
+
+ if (log2ArrayIndexScale < LOG2_ARRAY_INT_INDEX_SCALE) {
+ int wordTail = 1 << (LOG2_ARRAY_INT_INDEX_SCALE - log2ArrayIndexScale);
+ // Handle 4 bytes or 2 chars in the tail using int width
+ if (tail >= wordTail) {
+ long bi = ((long) wi) << LOG2_ARRAY_LONG_INDEX_SCALE;
+ int av = U.getIntUnaligned(a, aOffset + bi);
+ int bv = U.getIntUnaligned(b, bOffset + bi);
+ if (av != bv) {
+ int x = av ^ bv;
+ int o = BIG_ENDIAN
+ ? Integer.numberOfLeadingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale)
+ : Integer.numberOfTrailingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale);
+ return (wi << log2ValuesPerWidth) + o;
+ }
+ tail -= wordTail;
+ }
+ return ~tail;
+ }
+ else {
+ return ~tail;
+ }
+ }
+
+ // Booleans
+ // Each boolean element takes up one byte
+
+ static int mismatch(boolean[] a,
+ boolean[] b,
+ int length) {
+ int i = 0;
+ if (length > 7) {
+ i = vectorizedMismatch(
+ a, Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
+ b, Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
+ length, LOG2_ARRAY_BOOLEAN_INDEX_SCALE);
+ if (i >= 0)
+ return i;
+ i = length - ~i;
+ }
+ for (; i < length; i++) {
+ if (a[i] != b[i])
+ return i;
+ }
+ return -1;
+ }
+
+ static int mismatch(boolean[] a, int aFromIndex,
+ boolean[] b, int bFromIndex,
+ int length) {
+ int i = 0;
+ if (length > 7) {
+ int aOffset = Unsafe.ARRAY_BOOLEAN_BASE_OFFSET + aFromIndex;
+ int bOffset = Unsafe.ARRAY_BOOLEAN_BASE_OFFSET + bFromIndex;
+ i = vectorizedMismatch(
+ a, aOffset,
+ b, bOffset,
+ length, LOG2_ARRAY_BOOLEAN_INDEX_SCALE);
+ if (i >= 0)
+ return i;
+ i = length - ~i;
+ }
+ for (; i < length; i++) {
+ if (a[aFromIndex + i] != b[bFromIndex + i])
+ return i;
+ }
+ return -1;
+ }
+
+
+ // Bytes
+
+ /**
+ * Find the index of a mismatch between two arrays.
+ *
+ * <p>This method does not perform bounds checks. It is the responsibility
+ * of the caller to perform such bounds checks before calling this method.
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @param length the number of bytes from each array to check
+ * @return the index of a mismatch between the two arrays, otherwise -1 if
+ * no mismatch. The index will be within the range of (inclusive) 0 to
+ * (exclusive) the smaller of the two array lengths.
+ */
+ static int mismatch(byte[] a,
+ byte[] b,
+ int length) {
+ // ISSUE: defer to index receiving methods if performance is good
+ // assert length <= a.length
+ // assert length <= b.length
+
+ int i = 0;
+ if (length > 7) {
+ i = vectorizedMismatch(
+ a, Unsafe.ARRAY_BYTE_BASE_OFFSET,
+ b, Unsafe.ARRAY_BYTE_BASE_OFFSET,
+ length, LOG2_ARRAY_BYTE_INDEX_SCALE);
+ if (i >= 0)
+ return i;
+ // Align to tail
+ i = length - ~i;
+// assert i >= 0 && i <= 7;
+ }
+ // Tail < 8 bytes
+ for (; i < length; i++) {
+ if (a[i] != b[i])
+ return i;
+ }
+ return -1;
+ }
+
+ /**
+ * Find the relative index of a mismatch between two arrays starting from
+ * given indexes.
+ *
+ * <p>This method does not perform bounds checks. It is the responsibility
+ * of the caller to perform such bounds checks before calling this method.
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param aFromIndex the index of the first element (inclusive) in the first
+ * array to be compared
+ * @param b the second array to be tested for a mismatch
+ * @param bFromIndex the index of the first element (inclusive) in the
+ * second array to be compared
+ * @param length the number of bytes from each array to check
+ * @return the relative index of a mismatch between the two arrays,
+ * otherwise -1 if no mismatch. The index will be within the range of
+ * (inclusive) 0 to (exclusive) the smaller of the two array bounds.
+ */
+ static int mismatch(byte[] a, int aFromIndex,
+ byte[] b, int bFromIndex,
+ int length) {
+ // assert 0 <= aFromIndex < a.length
+ // assert 0 <= aFromIndex + length <= a.length
+ // assert 0 <= bFromIndex < b.length
+ // assert 0 <= bFromIndex + length <= b.length
+ // assert length >= 0
+
+ int i = 0;
+ if (length > 7) {
+ int aOffset = Unsafe.ARRAY_BYTE_BASE_OFFSET + aFromIndex;
+ int bOffset = Unsafe.ARRAY_BYTE_BASE_OFFSET + bFromIndex;
+ i = vectorizedMismatch(
+ a, aOffset,
+ b, bOffset,
+ length, LOG2_ARRAY_BYTE_INDEX_SCALE);
+ if (i >= 0)
+ return i;
+ i = length - ~i;
+ }
+ for (; i < length; i++) {
+ if (a[aFromIndex + i] != b[bFromIndex + i])
+ return i;
+ }
+ return -1;
+ }
+
+
+ // Chars
+
+ static int mismatch(char[] a,
+ char[] b,
+ int length) {
+ int i = 0;
+ if (length > 3) {
+ i = vectorizedMismatch(
+ a, Unsafe.ARRAY_CHAR_BASE_OFFSET,
+ b, Unsafe.ARRAY_CHAR_BASE_OFFSET,
+ length, LOG2_ARRAY_CHAR_INDEX_SCALE);
+ if (i >= 0)
+ return i;
+ i = length - ~i;
+ }
+ for (; i < length; i++) {
+ if (a[i] != b[i])
+ return i;
+ }
+ return -1;
+ }
+
+ static int mismatch(char[] a, int aFromIndex,
+ char[] b, int bFromIndex,
+ int length) {
+ int i = 0;
+ if (length > 3) {
+ int aOffset = Unsafe.ARRAY_CHAR_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_CHAR_INDEX_SCALE);
+ int bOffset = Unsafe.ARRAY_CHAR_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_CHAR_INDEX_SCALE);
+ i = vectorizedMismatch(
+ a, aOffset,
+ b, bOffset,
+ length, LOG2_ARRAY_CHAR_INDEX_SCALE);
+ if (i >= 0)
+ return i;
+ i = length - ~i;
+ }
+ for (; i < length; i++) {
+ if (a[aFromIndex + i] != b[bFromIndex + i])
+ return i;
+ }
+ return -1;
+ }
+
+
+ // Shorts
+
+ static int mismatch(short[] a,
+ short[] b,
+ int length) {
+ int i = 0;
+ if (length > 3) {
+ i = vectorizedMismatch(
+ a, Unsafe.ARRAY_SHORT_BASE_OFFSET,
+ b, Unsafe.ARRAY_SHORT_BASE_OFFSET,
+ length, LOG2_ARRAY_SHORT_INDEX_SCALE);
+ if (i >= 0)
+ return i;
+ i = length - ~i;
+ }
+ for (; i < length; i++) {
+ if (a[i] != b[i])
+ return i;
+ }
+ return -1;
+ }
+
+ static int mismatch(short[] a, int aFromIndex,
+ short[] b, int bFromIndex,
+ int length) {
+ int i = 0;
+ if (length > 3) {
+ int aOffset = Unsafe.ARRAY_SHORT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_SHORT_INDEX_SCALE);
+ int bOffset = Unsafe.ARRAY_SHORT_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_SHORT_INDEX_SCALE);
+ i = vectorizedMismatch(
+ a, aOffset,
+ b, bOffset,
+ length, LOG2_ARRAY_SHORT_INDEX_SCALE);
+ if (i >= 0)
+ return i;
+ i = length - ~i;
+ }
+ for (; i < length; i++) {
+ if (a[aFromIndex + i] != b[bFromIndex + i])
+ return i;
+ }
+ return -1;
+ }
+
+
+ // Ints
+
+ static int mismatch(int[] a,
+ int[] b,
+ int length) {
+ int i = 0;
+ if (length > 1) {
+ i = vectorizedMismatch(
+ a, Unsafe.ARRAY_INT_BASE_OFFSET,
+ b, Unsafe.ARRAY_INT_BASE_OFFSET,
+ length, LOG2_ARRAY_INT_INDEX_SCALE);
+ if (i >= 0)
+ return i;
+ i = length - ~i;
+ }
+ for (; i < length; i++) {
+ if (a[i] != b[i])
+ return i;
+ }
+ return -1;
+ }
+
+ static int mismatch(int[] a, int aFromIndex,
+ int[] b, int bFromIndex,
+ int length) {
+ int i = 0;
+ if (length > 1) {
+ int aOffset = Unsafe.ARRAY_INT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_INT_INDEX_SCALE);
+ int bOffset = Unsafe.ARRAY_INT_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_INT_INDEX_SCALE);
+ i = vectorizedMismatch(
+ a, aOffset,
+ b, bOffset,
+ length, LOG2_ARRAY_INT_INDEX_SCALE);
+ if (i >= 0)
+ return i;
+ i = length - ~i;
+ }
+ for (; i < length; i++) {
+ if (a[aFromIndex + i] != b[bFromIndex + i])
+ return i;
+ }
+ return -1;
+ }
+
+
+ // Floats
+
+ static int mismatch(float[] a,
+ float[] b,
+ int length) {
+ return mismatch(a, 0, b, 0, length);
+ }
+
+ static int mismatch(float[] a, int aFromIndex,
+ float[] b, int bFromIndex,
+ int length) {
+ int i = 0;
+ if (length > 1) {
+ int aOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_FLOAT_INDEX_SCALE);
+ int bOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_FLOAT_INDEX_SCALE);
+ i = vectorizedMismatch(
+ a, aOffset,
+ b, bOffset,
+ length, LOG2_ARRAY_FLOAT_INDEX_SCALE);
+ // Mismatched
+ if (i >= 0) {
+ // Check if mismatch is not associated with two NaN values
+ if (!Float.isNaN(a[aFromIndex + i]) || !Float.isNaN(b[bFromIndex + i]))
+ return i;
+
+ // Mismatch on two different NaN values that are normalized to match
+ // Fall back to slow mechanism
+ // ISSUE: Consider looping over vectorizedMismatch adjusting ranges
+ // However, requires that returned value be relative to input ranges
+ i++;
+ }
+ // Matched
+ else {
+ i = length - ~i;
+ }
+ }
+ for (; i < length; i++) {
+ if (Float.floatToIntBits(a[aFromIndex + i]) != Float.floatToIntBits(b[bFromIndex + i]))
+ return i;
+ }
+ return -1;
+ }
+
+ // 64 bit sizes
+
+ // Long
+
+ static int mismatch(long[] a,
+ long[] b,
+ int length) {
+ if (length == 0) {
+ return -1;
+ }
+ int i = vectorizedMismatch(
+ a, Unsafe.ARRAY_LONG_BASE_OFFSET,
+ b, Unsafe.ARRAY_LONG_BASE_OFFSET,
+ length, LOG2_ARRAY_LONG_INDEX_SCALE);
+ return i >= 0 ? i : -1;
+ }
+
+ static int mismatch(long[] a, int aFromIndex,
+ long[] b, int bFromIndex,
+ int length) {
+ if (length == 0) {
+ return -1;
+ }
+ int aOffset = Unsafe.ARRAY_LONG_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_LONG_INDEX_SCALE);
+ int bOffset = Unsafe.ARRAY_LONG_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_LONG_INDEX_SCALE);
+ int i = vectorizedMismatch(
+ a, aOffset,
+ b, bOffset,
+ length, LOG2_ARRAY_LONG_INDEX_SCALE);
+ return i >= 0 ? i : -1;
+ }
+
+
+ // Double
+
+ static int mismatch(double[] a,
+ double[] b,
+ int length) {
+ return mismatch(a, 0, b, 0, length);
+ }
+
+ static int mismatch(double[] a, int aFromIndex,
+ double[] b, int bFromIndex,
+ int length) {
+ if (length == 0) {
+ return -1;
+ }
+ int aOffset = Unsafe.ARRAY_DOUBLE_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_DOUBLE_INDEX_SCALE);
+ int bOffset = Unsafe.ARRAY_DOUBLE_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_DOUBLE_INDEX_SCALE);
+ int i = vectorizedMismatch(
+ a, aOffset,
+ b, bOffset,
+ length, LOG2_ARRAY_DOUBLE_INDEX_SCALE);
+ if (i >= 0) {
+ // Check if mismatch is not associated with two NaN values
+ if (!Double.isNaN(a[aFromIndex + i]) || !Double.isNaN(b[bFromIndex + i]))
+ return i;
+
+ // Mismatch on two different NaN values that are normalized to match
+ // Fall back to slow mechanism
+ // ISSUE: Consider looping over vectorizedMismatch adjusting ranges
+ // However, requires that returned value be relative to input ranges
+ i++;
+ for (; i < length; i++) {
+ if (Double.doubleToLongBits(a[aFromIndex + i]) != Double.doubleToLongBits(b[bFromIndex + i]))
+ return i;
+ }
+ }
+
+ return -1;
+ }
+}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java Thu Jan 14 20:57:33 2016 -0800
@@ -39,6 +39,7 @@
import java.util.Collection;
import java.util.Date;
import java.util.concurrent.TimeUnit;
+import jdk.internal.vm.annotation.ReservedStackAccess;
/**
* Provides a framework for implementing blocking locks and related
@@ -886,6 +887,7 @@
* @param arg the acquire argument
* @return {@code true} if interrupted while waiting
*/
+ @ReservedStackAccess
final boolean acquireQueued(final Node node, int arg) {
try {
boolean interrupted = false;
@@ -1218,6 +1220,7 @@
* {@link #tryAcquire} but is otherwise uninterpreted and
* can represent anything you like.
*/
+ @ReservedStackAccess
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
@@ -1281,6 +1284,7 @@
* can represent anything you like.
* @return the value returned from {@link #tryRelease}
*/
+ @ReservedStackAccess
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
@@ -1361,6 +1365,7 @@
* and can represent anything you like.
* @return the value returned from {@link #tryReleaseShared}
*/
+ @ReservedStackAccess
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantLock.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantLock.java Thu Jan 14 20:57:33 2016 -0800
@@ -37,6 +37,7 @@
import java.util.Collection;
import java.util.concurrent.TimeUnit;
+import jdk.internal.vm.annotation.ReservedStackAccess;
/**
* A reentrant mutual exclusion {@link Lock} with the same basic
@@ -127,6 +128,7 @@
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
*/
+ @ReservedStackAccess
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
@@ -146,6 +148,7 @@
return false;
}
+ @ReservedStackAccess
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
@@ -203,6 +206,7 @@
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
+ @ReservedStackAccess
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
@@ -229,6 +233,7 @@
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
+ @ReservedStackAccess
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/vm/annotation/DontInline.java Thu Jan 14 20:57:33 2016 -0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 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 jdk.internal.vm.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * A method or constructor may be annotated as "don't inline" if the inlining of
+ * this method should not be performed by the HotSpot VM.
+ * <p>
+ * This annotation must be used sparingly. It is useful when the only
+ * reasonable alternative is to bind the name of a specific method or
+ * constructor into the HotSpot VM for special handling by the inlining policy.
+ * This annotation must not be relied on as an alternative to avoid tuning the
+ * VM's inlining policy. In a few cases, it may act as a temporary workaround
+ * until the profiling and inlining performed by the HotSpot VM is sufficiently
+ * improved.
+ *
+ * @implNote
+ * This annotation only takes effect for methods or constructors of classes
+ * loaded by the boot loader. Annotations on methods or constructors of classes
+ * loaded outside of the boot loader are ignored.
+ */
+@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface DontInline {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/vm/annotation/ForceInline.java Thu Jan 14 20:57:33 2016 -0800
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 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 jdk.internal.vm.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * A method or constructor may be annotated as "force inline" if the standard
+ * inlining metrics are to be ignored when the HotSpot VM inlines the method
+ * or constructor.
+ * <p>
+ * This annotation must be used sparingly. It is useful when the only
+ * reasonable alternative is to bind the name of a specific method or
+ * constructor into the HotSpot VM for special handling by the inlining policy.
+ * This annotation must not be relied on as an alternative to avoid tuning the
+ * VM's inlining policy. In a few cases, it may act as a temporary workaround
+ * until the profiling and inlining performed by the HotSpot VM is sufficiently
+ * improved.
+ *
+ * @implNote
+ * This annotation only takes effect for methods or constructors of classes
+ * loaded by the boot loader. Annotations on methods or constructors of classes
+ * loaded outside of the boot loader are ignored.
+ */
+@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ForceInline {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/vm/annotation/ReservedStackAccess.java Thu Jan 14 20:57:33 2016 -0800
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package jdk.internal.vm.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * <p>An annotation expressing that a method is especially sensitive
+ * to stack overflows. This is a hint the JVM can use to grant access to
+ * extra stack space when executing this code if such feature is supported
+ * by the JVM. The JVM is free to ignore this annotation.
+ *
+ * A possible way for the JVM to improve the execution context for methods
+ * with this annotation is to reserve part of the thread's execution stack
+ * for them. Access to this section of the stack would be denied by default
+ * but could be granted if the JVM detects a possible stack overflow and
+ * the thread's call stack includes at least one annotated method. Even if
+ * access to this reserved area has been granted, the JVM might decide to
+ * throw a delayed StackOverflowError when the thread exits the annotated
+ * method.
+ *
+ * @since 1.9
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+public @interface ReservedStackAccess { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/vm/annotation/Stable.java Thu Jan 14 20:57:33 2016 -0800
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 jdk.internal.vm.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * A field may be annotated as stable if all of its component variables
+ * changes value at most once.
+ * A field's value counts as its component value.
+ * If the field is typed as an array, then all the non-null components
+ * of the array, of depth up to the rank of the field's array type,
+ * also count as component values.
+ * By extension, any variable (either array or field) which has annotated
+ * as stable is called a stable variable, and its non-null or non-zero
+ * value is called a stable value.
+ * <p>
+ * Since all fields begin with a default value of null for references
+ * (resp., zero for primitives), it follows that this annotation indicates
+ * that the first non-null (resp., non-zero) value stored in the field
+ * will never be changed.
+ * <p>
+ * If the field is not of an array type, there are no array elements,
+ * then the value indicated as stable is simply the value of the field.
+ * If the dynamic type of the field value is an array but the static type
+ * is not, the components of the array are <em>not</em> regarded as stable.
+ * <p>
+ * If the field is an array type, then both the field value and
+ * all the components of the field value (if the field value is non-null)
+ * are indicated to be stable.
+ * If the field type is an array type with rank {@code N > 1},
+ * then each component of the field value (if the field value is non-null),
+ * is regarded as a stable array of rank {@code N-1}.
+ * <p>
+ * Fields which are declared {@code final} may also be annotated as stable.
+ * Since final fields already behave as stable values, such an annotation
+ * conveys no additional information regarding change of the field's value, but
+ * still conveys information regarding change of additional components values if
+ * the type of the field is an array type (as described above).
+ * <p>
+ * The HotSpot VM relies on this annotation to promote a non-null (resp.,
+ * non-zero) component value to a constant, thereby enabling superior
+ * optimizations of code depending on such a value (such as constant folding).
+ * More specifically, the HotSpot VM will process non-null stable fields (final
+ * or otherwise) in a similar manner to static final fields with respect to
+ * promoting the field's value to a constant. Thus, placing aside the
+ * differences for null/non-null values and arrays, a final stable field is
+ * treated as if it is really final from both the Java language and the HotSpot
+ * VM.
+ * <p>
+ * It is (currently) undefined what happens if a field annotated as stable
+ * is given a third value (by explicitly updating a stable field, a component of
+ * a stable array, or a final stable field via reflection or other means).
+ * Since the HotSpot VM promotes a non-null component value to constant, it may
+ * be that the Java memory model would appear to be broken, if such a constant
+ * (the second value of the field) is used as the value of the field even after
+ * the field value has changed (to a third value).
+ *
+ * @implNote
+ * This annotation only takes effect for fields of classes loaded by the boot
+ * loader. Annoations on fields of classes loaded outside of the boot loader
+ * are ignored.
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Stable {
+}
--- a/jdk/src/java.base/share/classes/sun/invoke/anon/AnonymousClassLoader.java Thu Jan 14 12:04:19 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,234 +0,0 @@
-/*
- * Copyright (c) 2008, 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 sun.invoke.anon;
-
-import java.io.EOFException;
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-/**
- * Anonymous class loader. Will load any valid classfile, producing
- * a {@link Class} metaobject, without installing that class in the
- * system dictionary. Therefore, {@link Class#forName(String)} will never
- * produce a reference to an anonymous class.
- * <p>
- * The access permissions of the anonymous class are borrowed from
- * a <em>host class</em>. The new class behaves as if it were an
- * inner class of the host class. It can access the host's private
- * members, if the creator of the class loader has permission to
- * do so (or to create accessible reflective objects).
- * <p>
- * When the anonymous class is loaded, elements of its constant pool
- * can be patched to new values. This provides a hook to pre-resolve
- * named classes in the constant pool to other classes, including
- * anonymous ones. Also, string constants can be pre-resolved to
- * any reference. (The verifier treats non-string, non-class reference
- * constants as plain objects.)
- * <p>
- * Why include the patching function? It makes some use cases much easier.
- * Second, the constant pool needed some internal patching anyway,
- * to anonymize the loaded class itself. Finally, if you are going
- * to use this seriously, you'll want to build anonymous classes
- * on top of pre-existing anonymous classes, and that requires patching.
- *
- * <p>%%% TO-DO:
- * <ul>
- * <li>needs better documentation</li>
- * <li>needs more security work (for safe delegation)</li>
- * <li>needs a clearer story about error processing</li>
- * <li>patch member references also (use ';' as delimiter char)</li>
- * <li>patch method references to (conforming) method handles</li>
- * </ul>
- *
- * @author jrose
- * @author Remi Forax
- * @see <a href="http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm">
- * http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm</a>
- */
-
-public class AnonymousClassLoader {
- final Class<?> hostClass;
-
- // Privileged constructor.
- private AnonymousClassLoader(Class<?> hostClass) {
- this.hostClass = hostClass;
- }
-
- public static AnonymousClassLoader make(jdk.internal.misc.Unsafe unsafe, Class<?> hostClass) {
- if (unsafe == null) throw new NullPointerException();
- return new AnonymousClassLoader(hostClass);
- }
-
- public Class<?> loadClass(byte[] classFile) {
- if (defineAnonymousClass == null) {
- // no JVM support; try to fake an approximation
- try {
- return fakeLoadClass(new ConstantPoolParser(classFile).createPatch());
- } catch (InvalidConstantPoolFormatException ee) {
- throw new IllegalArgumentException(ee);
- }
- }
- return loadClass(classFile, null);
- }
-
- public Class<?> loadClass(ConstantPoolPatch classPatch) {
- if (defineAnonymousClass == null) {
- // no JVM support; try to fake an approximation
- return fakeLoadClass(classPatch);
- }
- Object[] patches = classPatch.patchArray;
- // Convert class names (this late in the game)
- // to use slash '/' instead of dot '.'.
- // Java likes dots, but the JVM likes slashes.
- for (int i = 0; i < patches.length; i++) {
- Object value = patches[i];
- if (value != null) {
- byte tag = classPatch.getTag(i);
- switch (tag) {
- case ConstantPoolVisitor.CONSTANT_Class:
- if (value instanceof String) {
- if (patches == classPatch.patchArray)
- patches = patches.clone();
- patches[i] = ((String)value).replace('.', '/');
- }
- break;
- case ConstantPoolVisitor.CONSTANT_Fieldref:
- case ConstantPoolVisitor.CONSTANT_Methodref:
- case ConstantPoolVisitor.CONSTANT_InterfaceMethodref:
- case ConstantPoolVisitor.CONSTANT_NameAndType:
- // When/if the JVM supports these patches,
- // we'll probably need to reformat them also.
- // Meanwhile, let the class loader create the error.
- break;
- }
- }
- }
- return loadClass(classPatch.outer.classFile, classPatch.patchArray);
- }
-
- private Class<?> loadClass(byte[] classFile, Object[] patchArray) {
- try {
- return (Class<?>)
- defineAnonymousClass.invoke(unsafe,
- hostClass, classFile, patchArray);
- } catch (Exception ex) {
- throwReflectedException(ex);
- throw new RuntimeException("error loading into "+hostClass, ex);
- }
- }
-
- private static void throwReflectedException(Exception ex) {
- if (ex instanceof InvocationTargetException) {
- Throwable tex = ((InvocationTargetException)ex).getTargetException();
- if (tex instanceof Error)
- throw (Error) tex;
- ex = (Exception) tex;
- }
- if (ex instanceof RuntimeException) {
- throw (RuntimeException) ex;
- }
- }
-
- private Class<?> fakeLoadClass(ConstantPoolPatch classPatch) {
- // Implementation:
- // 1. Make up a new name nobody has used yet.
- // 2. Inspect the tail-header of the class to find the this_class index.
- // 3. Patch the CONSTANT_Class for this_class to the new name.
- // 4. Add other CP entries required by (e.g.) string patches.
- // 5. Flatten Class constants down to their names, making sure that
- // the host class loader can pick them up again accurately.
- // 6. Generate the edited class file bytes.
- //
- // Potential limitations:
- // * The class won't be truly anonymous, and may interfere with others.
- // * Flattened class constants might not work, because of loader issues.
- // * Pseudo-string constants will not flatten down to real strings.
- // * Method handles will (of course) fail to flatten to linkage strings.
- if (true) throw new UnsupportedOperationException("NYI");
- Object[] cpArray;
- try {
- cpArray = classPatch.getOriginalCP();
- } catch (InvalidConstantPoolFormatException ex) {
- throw new RuntimeException(ex);
- }
- int thisClassIndex = classPatch.getParser().getThisClassIndex();
- String thisClassName = (String) cpArray[thisClassIndex];
- synchronized (AnonymousClassLoader.class) {
- thisClassName = thisClassName+"\\|"+(++fakeNameCounter);
- }
- classPatch.putUTF8(thisClassIndex, thisClassName);
- byte[] classFile = null;
- return unsafe.defineClass(null, classFile, 0, classFile.length,
- hostClass.getClassLoader(),
- hostClass.getProtectionDomain());
- }
- private static int fakeNameCounter = 99999;
-
- // ignore two warnings on this line:
- private static jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
- // preceding line requires that this class be on the boot class path
-
- private static final Method defineAnonymousClass;
- static {
- Method dac = null;
- Class<? extends jdk.internal.misc.Unsafe> unsafeClass = unsafe.getClass();
- try {
- dac = unsafeClass.getMethod("defineAnonymousClass",
- Class.class,
- byte[].class,
- Object[].class);
- } catch (Exception ee) {
- dac = null;
- }
- defineAnonymousClass = dac;
- }
-
- private static void noJVMSupport() {
- throw new UnsupportedOperationException("no JVM support for anonymous classes");
- }
-
-
- private static native Class<?> loadClassInternal(Class<?> hostClass,
- byte[] classFile,
- Object[] patchArray);
-
- public static byte[] readClassFile(Class<?> templateClass) throws IOException {
- String templateName = templateClass.getName();
- int lastDot = templateName.lastIndexOf('.');
- java.net.URL url = templateClass.getResource(templateName.substring(lastDot+1)+".class");
- java.net.URLConnection connection = url.openConnection();
- int contentLength = connection.getContentLength();
- if (contentLength < 0)
- throw new IOException("invalid content length "+contentLength);
-
- byte[] b = connection.getInputStream().readAllBytes();
- if (b.length != contentLength)
- throw new EOFException("Expected:" + contentLength + ", read:" + b.length);
-
- return b;
- }
-}
--- a/jdk/src/java.base/share/classes/sun/invoke/anon/ConstantPoolParser.java Thu Jan 14 12:04:19 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,368 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.invoke.anon;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-
-import static sun.invoke.anon.ConstantPoolVisitor.*;
-
-/** A constant pool parser.
- */
-public class ConstantPoolParser {
- final byte[] classFile;
- final byte[] tags;
- final char[] firstHeader; // maghi, maglo, minor, major, cplen
-
- // these are filled in on first parse:
- int endOffset;
- char[] secondHeader; // flags, this_class, super_class, intlen
-
- // used to decode UTF8 array
- private char[] charArray = new char[80];
-
- /** Creates a constant pool parser.
- * @param classFile an array of bytes containing a class.
- * @throws InvalidConstantPoolFormatException if the header of the class has errors.
- */
- public ConstantPoolParser(byte[] classFile) throws InvalidConstantPoolFormatException {
- this.classFile = classFile;
- this.firstHeader = parseHeader(classFile);
- this.tags = new byte[firstHeader[4]];
- }
-
- /** Create a constant pool parser by loading the bytecodes of the
- * class taken as argument.
- *
- * @param templateClass the class to parse.
- *
- * @throws IOException raised if an I/O occurs when loading
- * the bytecode of the template class.
- * @throws InvalidConstantPoolFormatException if the header of the class has errors.
- *
- * @see #ConstantPoolParser(byte[])
- * @see AnonymousClassLoader#readClassFile(Class)
- */
- public ConstantPoolParser(Class<?> templateClass) throws IOException, InvalidConstantPoolFormatException {
- this(AnonymousClassLoader.readClassFile(templateClass));
- }
-
- /** Creates an empty patch to patch the class file
- * used by the current parser.
- * @return a new class patch.
- */
- public ConstantPoolPatch createPatch() {
- return new ConstantPoolPatch(this);
- }
-
- /** Report the tag of the indicated CP entry.
- * @param index
- * @return one of {@link ConstantPoolVisitor#CONSTANT_Utf8}, etc.
- */
- public byte getTag(int index) {
- getEndOffset(); // trigger an exception if we haven't parsed yet
- return tags[index];
- }
-
- /** Report the length of the constant pool. */
- public int getLength() {
- return firstHeader[4];
- }
-
- /** Report the offset, within the class file, of the start of the constant pool. */
- public int getStartOffset() {
- return firstHeader.length * 2;
- }
-
- /** Report the offset, within the class file, of the end of the constant pool. */
- public int getEndOffset() {
- if (endOffset == 0)
- throw new IllegalStateException("class file has not yet been parsed");
- return endOffset;
- }
-
- /** Report the CP index of this class's own name. */
- public int getThisClassIndex() {
- getEndOffset(); // provoke exception if not yet parsed
- return secondHeader[1];
- }
-
- /** Report the total size of the class file. */
- public int getTailLength() {
- return classFile.length - getEndOffset();
- }
-
- /** Write the head (header plus constant pool)
- * of the class file to the indicated stream.
- */
- public void writeHead(OutputStream out) throws IOException {
- out.write(classFile, 0, getEndOffset());
- }
-
- /** Write the head (header plus constant pool)
- * of the class file to the indicated stream,
- * incorporating the non-null entries of the given array
- * as patches.
- */
- void writePatchedHead(OutputStream out, Object[] patchArray) {
- // this will be useful to partially emulate the class loader on old JVMs
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- /** Write the tail (everything after the constant pool)
- * of the class file to the indicated stream.
- */
- public void writeTail(OutputStream out) throws IOException {
- out.write(classFile, getEndOffset(), getTailLength());
- }
-
- private static char[] parseHeader(byte[] classFile) throws InvalidConstantPoolFormatException {
- char[] result = new char[5];
- ByteBuffer buffer = ByteBuffer.wrap(classFile);
- for (int i = 0; i < result.length; i++)
- result[i] = (char) getUnsignedShort(buffer);
- int magic = result[0] << 16 | result[1] << 0;
- if (magic != 0xCAFEBABE)
- throw new InvalidConstantPoolFormatException("invalid magic number "+magic);
- // skip major, minor version
- int len = result[4];
- if (len < 1)
- throw new InvalidConstantPoolFormatException("constant pool length < 1");
- return result;
- }
-
- /** Parse the constant pool of the class
- * calling a method visit* each time a constant pool entry is parsed.
- *
- * The order of the calls to visit* is not guaranteed to be the same
- * than the order of the constant pool entry in the bytecode array.
- *
- * @param visitor
- * @throws InvalidConstantPoolFormatException
- */
- public void parse(ConstantPoolVisitor visitor) throws InvalidConstantPoolFormatException {
- ByteBuffer buffer = ByteBuffer.wrap(classFile);
- buffer.position(getStartOffset()); //skip header
-
- Object[] values = new Object[getLength()];
- try {
- parseConstantPool(buffer, values, visitor);
- } catch(BufferUnderflowException e) {
- throw new InvalidConstantPoolFormatException(e);
- }
- if (endOffset == 0) {
- endOffset = buffer.position();
- secondHeader = new char[4];
- for (int i = 0; i < secondHeader.length; i++) {
- secondHeader[i] = (char) getUnsignedShort(buffer);
- }
- }
- resolveConstantPool(values, visitor);
- }
-
- private char[] getCharArray(int utfLength) {
- if (utfLength <= charArray.length)
- return charArray;
- return charArray = new char[utfLength];
- }
-
- private void parseConstantPool(ByteBuffer buffer, Object[] values, ConstantPoolVisitor visitor) throws InvalidConstantPoolFormatException {
- for (int i = 1; i < tags.length; ) {
- byte tag = (byte) getUnsignedByte(buffer);
- assert(tags[i] == 0 || tags[i] == tag);
- tags[i] = tag;
- switch (tag) {
- case CONSTANT_Utf8:
- int utfLen = getUnsignedShort(buffer);
- String value = getUTF8(buffer, utfLen, getCharArray(utfLen));
- visitor.visitUTF8(i, CONSTANT_Utf8, value);
- tags[i] = tag;
- values[i++] = value;
- break;
- case CONSTANT_Integer:
- visitor.visitConstantValue(i, tag, buffer.getInt());
- i++;
- break;
- case CONSTANT_Float:
- visitor.visitConstantValue(i, tag, buffer.getFloat());
- i++;
- break;
- case CONSTANT_Long:
- visitor.visitConstantValue(i, tag, buffer.getLong());
- i+=2;
- break;
- case CONSTANT_Double:
- visitor.visitConstantValue(i, tag, buffer.getDouble());
- i+=2;
- break;
-
- case CONSTANT_Class: // fall through:
- case CONSTANT_String:
- tags[i] = tag;
- values[i++] = new int[] { getUnsignedShort(buffer) };
- break;
-
- case CONSTANT_Fieldref: // fall through:
- case CONSTANT_Methodref: // fall through:
- case CONSTANT_InterfaceMethodref: // fall through:
- case CONSTANT_NameAndType:
- tags[i] = tag;
- values[i++] = new int[] { getUnsignedShort(buffer), getUnsignedShort(buffer) };
- break;
- default:
- throw new AssertionError("invalid constant "+tag);
- }
- }
- }
-
- private void resolveConstantPool(Object[] values, ConstantPoolVisitor visitor) {
- // clean out the int[] values, which are temporary
- for (int beg = 1, end = values.length-1, beg2, end2;
- beg <= end;
- beg = beg2, end = end2) {
- beg2 = end; end2 = beg-1;
- //System.out.println("CP resolve pass: "+beg+".."+end);
- for (int i = beg; i <= end; i++) {
- Object value = values[i];
- if (!(value instanceof int[]))
- continue;
- int[] array = (int[]) value;
- byte tag = tags[i];
- switch (tag) {
- case CONSTANT_String:
- String stringBody = (String) values[array[0]];
- visitor.visitConstantString(i, tag, stringBody, array[0]);
- values[i] = null;
- break;
- case CONSTANT_Class: {
- String className = (String) values[array[0]];
- // use the external form favored by Class.forName:
- className = className.replace('/', '.');
- visitor.visitConstantString(i, tag, className, array[0]);
- values[i] = className;
- break;
- }
- case CONSTANT_NameAndType: {
- String memberName = (String) values[array[0]];
- String signature = (String) values[array[1]];
- visitor.visitDescriptor(i, tag, memberName, signature,
- array[0], array[1]);
- values[i] = new String[] {memberName, signature};
- break;
- }
- case CONSTANT_Fieldref: // fall through:
- case CONSTANT_Methodref: // fall through:
- case CONSTANT_InterfaceMethodref: {
- Object className = values[array[0]];
- Object nameAndType = values[array[1]];
- if (!(className instanceof String) ||
- !(nameAndType instanceof String[])) {
- // one more pass is needed
- if (beg2 > i) beg2 = i;
- if (end2 < i) end2 = i;
- continue;
- }
- String[] nameAndTypeArray = (String[]) nameAndType;
- visitor.visitMemberRef(i, tag,
- (String)className,
- nameAndTypeArray[0],
- nameAndTypeArray[1],
- array[0], array[1]);
- values[i] = null;
- }
- break;
- default:
- continue;
- }
- }
- }
- }
-
- private static int getUnsignedByte(ByteBuffer buffer) {
- return buffer.get() & 0xFF;
- }
-
- private static int getUnsignedShort(ByteBuffer buffer) {
- int b1 = getUnsignedByte(buffer);
- int b2 = getUnsignedByte(buffer);
- return (b1 << 8) + (b2 << 0);
- }
-
- private static String getUTF8(ByteBuffer buffer, int utfLen, char[] charArray) throws InvalidConstantPoolFormatException {
- int utfLimit = buffer.position() + utfLen;
- int index = 0;
- while (buffer.position() < utfLimit) {
- int c = buffer.get() & 0xff;
- if (c > 127) {
- buffer.position(buffer.position() - 1);
- return getUTF8Extended(buffer, utfLimit, charArray, index);
- }
- charArray[index++] = (char)c;
- }
- return new String(charArray, 0, index);
- }
-
- private static String getUTF8Extended(ByteBuffer buffer, int utfLimit, char[] charArray, int index) throws InvalidConstantPoolFormatException {
- int c, c2, c3;
- while (buffer.position() < utfLimit) {
- c = buffer.get() & 0xff;
- switch (c >> 4) {
- case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
- /* 0xxxxxxx*/
- charArray[index++] = (char)c;
- break;
- case 12: case 13:
- /* 110x xxxx 10xx xxxx*/
- c2 = buffer.get();
- if ((c2 & 0xC0) != 0x80)
- throw new InvalidConstantPoolFormatException(
- "malformed input around byte " + buffer.position());
- charArray[index++] = (char)(((c & 0x1F) << 6) |
- (c2 & 0x3F));
- break;
- case 14:
- /* 1110 xxxx 10xx xxxx 10xx xxxx */
- c2 = buffer.get();
- c3 = buffer.get();
- if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80))
- throw new InvalidConstantPoolFormatException(
- "malformed input around byte " + (buffer.position()));
- charArray[index++] = (char)(((c & 0x0F) << 12) |
- ((c2 & 0x3F) << 6) |
- ((c3 & 0x3F) << 0));
- break;
- default:
- /* 10xx xxxx, 1111 xxxx */
- throw new InvalidConstantPoolFormatException(
- "malformed input around byte " + buffer.position());
- }
- }
- // The number of chars produced may be less than utflen
- return new String(charArray, 0, index);
- }
-}
--- a/jdk/src/java.base/share/classes/sun/invoke/anon/ConstantPoolPatch.java Thu Jan 14 12:04:19 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,503 +0,0 @@
-/*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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.invoke.anon;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.Map;
-
-import static sun.invoke.anon.ConstantPoolVisitor.*;
-
-/** A class and its patched constant pool.
- *
- * This class allow to modify (patch) a constant pool
- * by changing the value of its entry.
- * Entry are referenced using index that can be get
- * by parsing the constant pool using
- * {@link ConstantPoolParser#parse(ConstantPoolVisitor)}.
- *
- * @see ConstantPoolVisitor
- * @see ConstantPoolParser#createPatch()
- */
-public class ConstantPoolPatch {
- final ConstantPoolParser outer;
- final Object[] patchArray;
-
- ConstantPoolPatch(ConstantPoolParser outer) {
- this.outer = outer;
- this.patchArray = new Object[outer.getLength()];
- }
-
- /** Create a {@link ConstantPoolParser} and
- * a {@link ConstantPoolPatch} in one step.
- * Equivalent to {@code new ConstantPoolParser(classFile).createPatch()}.
- *
- * @param classFile an array of bytes containing a class.
- * @see #ConstantPoolParser(Class)
- */
- public ConstantPoolPatch(byte[] classFile) throws InvalidConstantPoolFormatException {
- this(new ConstantPoolParser(classFile));
- }
-
- /** Create a {@link ConstantPoolParser} and
- * a {@link ConstantPoolPatch} in one step.
- * Equivalent to {@code new ConstantPoolParser(templateClass).createPatch()}.
- *
- * @param templateClass the class to parse.
- * @see #ConstantPoolParser(Class)
- */
- public ConstantPoolPatch(Class<?> templateClass) throws IOException, InvalidConstantPoolFormatException {
- this(new ConstantPoolParser(templateClass));
- }
-
-
- /** Creates a patch from an existing patch.
- * All changes are copied from that patch.
- * @param patch a patch
- *
- * @see ConstantPoolParser#createPatch()
- */
- public ConstantPoolPatch(ConstantPoolPatch patch) {
- outer = patch.outer;
- patchArray = patch.patchArray.clone();
- }
-
- /** Which parser built this patch? */
- public ConstantPoolParser getParser() {
- return outer;
- }
-
- /** Report the tag at the given index in the constant pool. */
- public byte getTag(int index) {
- return outer.getTag(index);
- }
-
- /** Report the current patch at the given index of the constant pool.
- * Null means no patch will be made.
- * To observe the unpatched entry at the given index, use
- * {@link #getParser()}{@code .}@link ConstantPoolParser#parse(ConstantPoolVisitor)}
- */
- public Object getPatch(int index) {
- Object value = patchArray[index];
- if (value == null) return null;
- switch (getTag(index)) {
- case CONSTANT_Fieldref:
- case CONSTANT_Methodref:
- case CONSTANT_InterfaceMethodref:
- if (value instanceof String)
- value = stripSemis(2, (String) value);
- break;
- case CONSTANT_NameAndType:
- if (value instanceof String)
- value = stripSemis(1, (String) value);
- break;
- }
- return value;
- }
-
- /** Clear all patches. */
- public void clear() {
- Arrays.fill(patchArray, null);
- }
-
- /** Clear one patch. */
- public void clear(int index) {
- patchArray[index] = null;
- }
-
- /** Produce the patches as an array. */
- public Object[] getPatches() {
- return patchArray.clone();
- }
-
- /** Produce the original constant pool as an array. */
- public Object[] getOriginalCP() throws InvalidConstantPoolFormatException {
- return getOriginalCP(0, patchArray.length, -1);
- }
-
- /** Walk the constant pool, applying patches using the given map.
- *
- * @param utf8Map Utf8 strings to modify, if encountered
- * @param classMap Classes (or their names) to modify, if encountered
- * @param valueMap Constant values to modify, if encountered
- * @param deleteUsedEntries if true, delete map entries that are used
- */
- public void putPatches(final Map<String,String> utf8Map,
- final Map<String,Object> classMap,
- final Map<Object,Object> valueMap,
- boolean deleteUsedEntries) throws InvalidConstantPoolFormatException {
- final HashSet<String> usedUtf8Keys;
- final HashSet<String> usedClassKeys;
- final HashSet<Object> usedValueKeys;
- if (deleteUsedEntries) {
- usedUtf8Keys = (utf8Map == null) ? null : new HashSet<String>();
- usedClassKeys = (classMap == null) ? null : new HashSet<String>();
- usedValueKeys = (valueMap == null) ? null : new HashSet<Object>();
- } else {
- usedUtf8Keys = null;
- usedClassKeys = null;
- usedValueKeys = null;
- }
-
- outer.parse(new ConstantPoolVisitor() {
-
- @Override
- public void visitUTF8(int index, byte tag, String utf8) {
- putUTF8(index, utf8Map.get(utf8));
- if (usedUtf8Keys != null) usedUtf8Keys.add(utf8);
- }
-
- @Override
- public void visitConstantValue(int index, byte tag, Object value) {
- putConstantValue(index, tag, valueMap.get(value));
- if (usedValueKeys != null) usedValueKeys.add(value);
- }
-
- @Override
- public void visitConstantString(int index, byte tag, String name, int nameIndex) {
- if (tag == CONSTANT_Class) {
- putConstantValue(index, tag, classMap.get(name));
- if (usedClassKeys != null) usedClassKeys.add(name);
- } else {
- assert(tag == CONSTANT_String);
- visitConstantValue(index, tag, name);
- }
- }
- });
- if (usedUtf8Keys != null) utf8Map.keySet().removeAll(usedUtf8Keys);
- if (usedClassKeys != null) classMap.keySet().removeAll(usedClassKeys);
- if (usedValueKeys != null) valueMap.keySet().removeAll(usedValueKeys);
- }
-
- Object[] getOriginalCP(final int startIndex,
- final int endIndex,
- final int tagMask) throws InvalidConstantPoolFormatException {
- final Object[] cpArray = new Object[endIndex - startIndex];
- outer.parse(new ConstantPoolVisitor() {
-
- void show(int index, byte tag, Object value) {
- if (index < startIndex || index >= endIndex) return;
- if (((1 << tag) & tagMask) == 0) return;
- cpArray[index - startIndex] = value;
- }
-
- @Override
- public void visitUTF8(int index, byte tag, String utf8) {
- show(index, tag, utf8);
- }
-
- @Override
- public void visitConstantValue(int index, byte tag, Object value) {
- assert(tag != CONSTANT_String);
- show(index, tag, value);
- }
-
- @Override
- public void visitConstantString(int index, byte tag,
- String value, int j) {
- show(index, tag, value);
- }
-
- @Override
- public void visitMemberRef(int index, byte tag,
- String className, String memberName,
- String signature,
- int j, int k) {
- show(index, tag, new String[]{ className, memberName, signature });
- }
-
- @Override
- public void visitDescriptor(int index, byte tag,
- String memberName, String signature,
- int j, int k) {
- show(index, tag, new String[]{ memberName, signature });
- }
- });
- return cpArray;
- }
-
- /** Write the head (header plus constant pool)
- * of the patched class file to the indicated stream.
- */
- void writeHead(OutputStream out) throws IOException {
- outer.writePatchedHead(out, patchArray);
- }
-
- /** Write the tail (everything after the constant pool)
- * of the patched class file to the indicated stream.
- */
- void writeTail(OutputStream out) throws IOException {
- outer.writeTail(out);
- }
-
- private void checkConstantTag(byte tag, Object value) {
- if (value == null)
- throw new IllegalArgumentException(
- "invalid null constant value");
- if (classForTag(tag) != value.getClass())
- throw new IllegalArgumentException(
- "invalid constant value"
- + (tag == CONSTANT_None ? ""
- : " for tag "+tagName(tag))
- + " of class "+value.getClass());
- }
-
- private void checkTag(int index, byte putTag) {
- byte tag = outer.tags[index];
- if (tag != putTag)
- throw new IllegalArgumentException(
- "invalid put operation"
- + " for " + tagName(putTag)
- + " at index " + index + " found " + tagName(tag));
- }
-
- private void checkTagMask(int index, int tagBitMask) {
- byte tag = outer.tags[index];
- int tagBit = ((tag & 0x1F) == tag) ? (1 << tag) : 0;
- if ((tagBit & tagBitMask) == 0)
- throw new IllegalArgumentException(
- "invalid put operation"
- + " at index " + index + " found " + tagName(tag));
- }
-
- private static void checkMemberName(String memberName) {
- if (memberName.indexOf(';') >= 0)
- throw new IllegalArgumentException("memberName " + memberName + " contains a ';'");
- }
-
- /** Set the entry of the constant pool indexed by index to
- * a new string.
- *
- * @param index an index to a constant pool entry containing a
- * {@link ConstantPoolVisitor#CONSTANT_Utf8} value.
- * @param utf8 a string
- *
- * @see ConstantPoolVisitor#visitUTF8(int, byte, String)
- */
- public void putUTF8(int index, String utf8) {
- if (utf8 == null) { clear(index); return; }
- checkTag(index, CONSTANT_Utf8);
- patchArray[index] = utf8;
- }
-
- /** Set the entry of the constant pool indexed by index to
- * a new value, depending on its dynamic type.
- *
- * @param index an index to a constant pool entry containing a
- * one of the following structures:
- * {@link ConstantPoolVisitor#CONSTANT_Integer},
- * {@link ConstantPoolVisitor#CONSTANT_Float},
- * {@link ConstantPoolVisitor#CONSTANT_Long},
- * {@link ConstantPoolVisitor#CONSTANT_Double},
- * {@link ConstantPoolVisitor#CONSTANT_String}, or
- * {@link ConstantPoolVisitor#CONSTANT_Class}
- * @param value a boxed int, float, long or double; or a string or class object
- * @throws IllegalArgumentException if the type of the constant does not
- * match the constant pool entry type,
- * as reported by {@link #getTag(int)}
- *
- * @see #putConstantValue(int, byte, Object)
- * @see ConstantPoolVisitor#visitConstantValue(int, byte, Object)
- * @see ConstantPoolVisitor#visitConstantString(int, byte, String, int)
- */
- public void putConstantValue(int index, Object value) {
- if (value == null) { clear(index); return; }
- byte tag = tagForConstant(value.getClass());
- checkConstantTag(tag, value);
- checkTag(index, tag);
- patchArray[index] = value;
- }
-
- /** Set the entry of the constant pool indexed by index to
- * a new value.
- *
- * @param index an index to a constant pool entry matching the given tag
- * @param tag one of the following values:
- * {@link ConstantPoolVisitor#CONSTANT_Integer},
- * {@link ConstantPoolVisitor#CONSTANT_Float},
- * {@link ConstantPoolVisitor#CONSTANT_Long},
- * {@link ConstantPoolVisitor#CONSTANT_Double},
- * {@link ConstantPoolVisitor#CONSTANT_String}, or
- * {@link ConstantPoolVisitor#CONSTANT_Class}
- * @param value a boxed number, string, or class object
- * @throws IllegalArgumentException if the type of the constant does not
- * match the constant pool entry type, or if a class name contains
- * '/' or ';'
- *
- * @see #putConstantValue(int, Object)
- * @see ConstantPoolVisitor#visitConstantValue(int, byte, Object)
- * @see ConstantPoolVisitor#visitConstantString(int, byte, String, int)
- */
- public void putConstantValue(int index, byte tag, Object value) {
- if (value == null) { clear(index); return; }
- checkTag(index, tag);
- if (tag == CONSTANT_Class && value instanceof String) {
- checkClassName((String) value);
- } else if (tag == CONSTANT_String) {
- // the JVM accepts any object as a patch for a string
- } else {
- // make sure the incoming value is the right type
- checkConstantTag(tag, value);
- }
- checkTag(index, tag);
- patchArray[index] = value;
- }
-
- /** Set the entry of the constant pool indexed by index to
- * a new {@link ConstantPoolVisitor#CONSTANT_NameAndType} value.
- *
- * @param index an index to a constant pool entry containing a
- * {@link ConstantPoolVisitor#CONSTANT_NameAndType} value.
- * @param memberName a memberName
- * @param signature a signature
- * @throws IllegalArgumentException if memberName contains the character ';'
- *
- * @see ConstantPoolVisitor#visitDescriptor(int, byte, String, String, int, int)
- */
- public void putDescriptor(int index, String memberName, String signature) {
- checkTag(index, CONSTANT_NameAndType);
- checkMemberName(memberName);
- patchArray[index] = addSemis(memberName, signature);
- }
-
- /** Set the entry of the constant pool indexed by index to
- * a new {@link ConstantPoolVisitor#CONSTANT_Fieldref},
- * {@link ConstantPoolVisitor#CONSTANT_Methodref}, or
- * {@link ConstantPoolVisitor#CONSTANT_InterfaceMethodref} value.
- *
- * @param index an index to a constant pool entry containing a member reference
- * @param className a class name
- * @param memberName a field or method name
- * @param signature a field or method signature
- * @throws IllegalArgumentException if memberName contains the character ';'
- * or signature is not a correct signature
- *
- * @see ConstantPoolVisitor#visitMemberRef(int, byte, String, String, String, int, int)
- */
- public void putMemberRef(int index, byte tag,
- String className, String memberName, String signature) {
- checkTagMask(tag, CONSTANT_MemberRef_MASK);
- checkTag(index, tag);
- checkClassName(className);
- checkMemberName(memberName);
- if (signature.startsWith("(") == (tag == CONSTANT_Fieldref))
- throw new IllegalArgumentException("bad signature: "+signature);
- patchArray[index] = addSemis(className, memberName, signature);
- }
-
- private static final int CONSTANT_MemberRef_MASK =
- CONSTANT_Fieldref
- | CONSTANT_Methodref
- | CONSTANT_InterfaceMethodref;
-
- private static final Map<Class<?>, Byte> CONSTANT_VALUE_CLASS_TAG
- = new IdentityHashMap<Class<?>, Byte>(6);
- private static final Class<?>[] CONSTANT_VALUE_CLASS = new Class<?>[16];
- static {
- Object[][] values = {
- {Integer.class, CONSTANT_Integer},
- {Long.class, CONSTANT_Long},
- {Float.class, CONSTANT_Float},
- {Double.class, CONSTANT_Double},
- {String.class, CONSTANT_String},
- {Class.class, CONSTANT_Class}
- };
- for (Object[] value : values) {
- Class<?> cls = (Class<?>)value[0];
- Byte tag = (Byte) value[1];
- CONSTANT_VALUE_CLASS_TAG.put(cls, tag);
- CONSTANT_VALUE_CLASS[(byte)tag] = cls;
- }
- }
-
- static Class<?> classForTag(byte tag) {
- if ((tag & 0xFF) >= CONSTANT_VALUE_CLASS.length)
- return null;
- return CONSTANT_VALUE_CLASS[tag];
- }
-
- static byte tagForConstant(Class<?> cls) {
- Byte tag = CONSTANT_VALUE_CLASS_TAG.get(cls);
- return (tag == null) ? CONSTANT_None : (byte)tag;
- }
-
- private static void checkClassName(String className) {
- if (className.indexOf('/') >= 0 || className.indexOf(';') >= 0)
- throw new IllegalArgumentException("invalid class name " + className);
- }
-
- static String addSemis(String name, String... names) {
- StringBuilder buf = new StringBuilder(name.length() * 5);
- buf.append(name);
- for (String name2 : names) {
- buf.append(';').append(name2);
- }
- String res = buf.toString();
- assert(stripSemis(names.length, res)[0].equals(name));
- assert(stripSemis(names.length, res)[1].equals(names[0]));
- assert(names.length == 1 ||
- stripSemis(names.length, res)[2].equals(names[1]));
- return res;
- }
-
- static String[] stripSemis(int count, String string) {
- String[] res = new String[count+1];
- int pos = 0;
- for (int i = 0; i < count; i++) {
- int pos2 = string.indexOf(';', pos);
- if (pos2 < 0) pos2 = string.length(); // yuck
- res[i] = string.substring(pos, pos2);
- pos = pos2;
- }
- res[count] = string.substring(pos);
- return res;
- }
-
- public String toString() {
- StringBuilder buf = new StringBuilder(this.getClass().getName());
- buf.append("{");
- Object[] origCP = null;
- for (int i = 0; i < patchArray.length; i++) {
- if (patchArray[i] == null) continue;
- if (origCP != null) {
- buf.append(", ");
- } else {
- try {
- origCP = getOriginalCP();
- } catch (InvalidConstantPoolFormatException ee) {
- origCP = new Object[0];
- }
- }
- Object orig = (i < origCP.length) ? origCP[i] : "?";
- buf.append(orig).append("=").append(patchArray[i]);
- }
- buf.append("}");
- return buf.toString();
- }
-}
--- a/jdk/src/java.base/share/classes/sun/invoke/anon/ConstantPoolVisitor.java Thu Jan 14 12:04:19 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.invoke.anon;
-
-/**
- * A visitor called by {@link ConstantPoolParser#parse(ConstantPoolVisitor)}
- * when a constant pool entry is parsed.
- * <p>
- * A visit* method is called when a constant pool entry is parsed.
- * The first argument is always the constant pool index.
- * The second argument is always the constant pool tag,
- * even for methods like {@link #visitUTF8(int, byte, String)} which only apply to one tag.
- * String arguments refer to Utf8 or NameAndType entries declared elsewhere,
- * and are always accompanied by the indexes of those entries.
- * <p>
- * The order of the calls to the visit* methods is not necessarily related
- * to the order of the entries in the constant pool.
- * If one entry has a reference to another entry, the latter (lower-level)
- * entry will be visited first.
- * <p>
- * The following table shows the relation between constant pool entry
- * types and the corresponding visit* methods:
- *
- * <table border=1 cellpadding=5 summary="constant pool visitor methods">
- * <tr><th>Tag(s)</th><th>Method</th></tr>
- * <tr>
- * <td>{@link #CONSTANT_Utf8}</td>
- * <td>{@link #visitUTF8(int, byte, String)}</td>
- * </tr><tr>
- * <td>{@link #CONSTANT_Integer}, {@link #CONSTANT_Float},
- * {@link #CONSTANT_Long}, {@link #CONSTANT_Double}</td>
- * <td>{@link #visitConstantValue(int, byte, Object)}</td>
- * </tr><tr>
- * <td>{@link #CONSTANT_String}, {@link #CONSTANT_Class}</td>
- * <td>{@link #visitConstantString(int, byte, String, int)}</td>
- * </tr><tr>
- * <td>{@link #CONSTANT_NameAndType}</td>
- * <td>{@link #visitDescriptor(int, byte, String, String, int, int)}</td>
- * </tr><tr>
- * <td>{@link #CONSTANT_Fieldref},
- * {@link #CONSTANT_Methodref},
- * {@link #CONSTANT_InterfaceMethodref}</td>
- * <td>{@link #visitMemberRef(int, byte, String, String, String, int, int)}</td>
- * </tr>
- * </table>
- *
- * @see ConstantPoolPatch
- * @author Remi Forax
- * @author jrose
- */
-public class ConstantPoolVisitor {
- /** Called each time an UTF8 constant pool entry is found.
- * @param index the constant pool index
- * @param tag always {@link #CONSTANT_Utf8}
- * @param utf8 string encoded in modified UTF-8 format passed as a {@code String}
- *
- * @see ConstantPoolPatch#putUTF8(int, String)
- */
- public void visitUTF8(int index, byte tag, String utf8) {
- // do nothing
- }
-
- /** Called for each constant pool entry that encodes an integer,
- * a float, a long, or a double.
- * Constant strings and classes are not managed by this method but
- * by {@link #visitConstantString(int, byte, String, int)}.
- *
- * @param index the constant pool index
- * @param tag one of {@link #CONSTANT_Integer},
- * {@link #CONSTANT_Float},
- * {@link #CONSTANT_Long},
- * or {@link #CONSTANT_Double}
- * @param value encoded value
- *
- * @see ConstantPoolPatch#putConstantValue(int, Object)
- */
- public void visitConstantValue(int index, byte tag, Object value) {
- // do nothing
- }
-
- /** Called for each constant pool entry that encodes a string or a class.
- * @param index the constant pool index
- * @param tag one of {@link #CONSTANT_String},
- * {@link #CONSTANT_Class},
- * @param name string body or class name (using dot separator)
- * @param nameIndex the index of the Utf8 string for the name
- *
- * @see ConstantPoolPatch#putConstantValue(int, byte, Object)
- */
- public void visitConstantString(int index, byte tag,
- String name, int nameIndex) {
- // do nothing
- }
-
- /** Called for each constant pool entry that encodes a name and type.
- * @param index the constant pool index
- * @param tag always {@link #CONSTANT_NameAndType}
- * @param memberName a field or method name
- * @param signature the member signature
- * @param memberNameIndex index of the Utf8 string for the member name
- * @param signatureIndex index of the Utf8 string for the signature
- *
- * @see ConstantPoolPatch#putDescriptor(int, String, String)
- */
- public void visitDescriptor(int index, byte tag,
- String memberName, String signature,
- int memberNameIndex, int signatureIndex) {
- // do nothing
- }
-
- /** Called for each constant pool entry that encodes a field or method.
- * @param index the constant pool index
- * @param tag one of {@link #CONSTANT_Fieldref},
- * or {@link #CONSTANT_Methodref},
- * or {@link #CONSTANT_InterfaceMethodref}
- * @param className the class name (using dot separator)
- * @param memberName name of the field or method
- * @param signature the field or method signature
- * @param classNameIndex index of the Utf8 string for the class name
- * @param descriptorIndex index of the NameAndType descriptor constant
- *
- * @see ConstantPoolPatch#putMemberRef(int, byte, String, String, String)
- */
- public void visitMemberRef(int index, byte tag,
- String className, String memberName, String signature,
- int classNameIndex, int descriptorIndex) {
- // do nothing
- }
-
- public static final byte
- CONSTANT_None = 0,
- CONSTANT_Utf8 = 1,
- //CONSTANT_Unicode = 2, /* unused */
- CONSTANT_Integer = 3,
- CONSTANT_Float = 4,
- CONSTANT_Long = 5,
- CONSTANT_Double = 6,
- CONSTANT_Class = 7,
- CONSTANT_String = 8,
- CONSTANT_Fieldref = 9,
- CONSTANT_Methodref = 10,
- CONSTANT_InterfaceMethodref = 11,
- CONSTANT_NameAndType = 12;
-
- private static String[] TAG_NAMES = {
- "Empty",
- "Utf8",
- null, //"Unicode",
- "Integer",
- "Float",
- "Long",
- "Double",
- "Class",
- "String",
- "Fieldref",
- "Methodref",
- "InterfaceMethodref",
- "NameAndType"
- };
-
- public static String tagName(byte tag) {
- String name = null;
- if ((tag & 0xFF) < TAG_NAMES.length)
- name = TAG_NAMES[tag];
- if (name == null)
- name = "Unknown#"+(tag&0xFF);
- return name;
- }
-}
--- a/jdk/src/java.base/share/classes/sun/invoke/anon/InvalidConstantPoolFormatException.java Thu Jan 14 12:04:19 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.invoke.anon;
-
-/** Exception used when there is an error in the constant pool
- * format.
- */
-public class InvalidConstantPoolFormatException extends Exception {
- private static final long serialVersionUID=-6103888330523770949L;
-
- public InvalidConstantPoolFormatException(String message,Throwable cause) {
- super(message,cause);
- }
-
- public InvalidConstantPoolFormatException(String message) {
- super(message);
- }
-
- public InvalidConstantPoolFormatException(Throwable cause) {
- super(cause);
- }
-}
--- a/jdk/src/java.base/share/classes/sun/misc/Unsafe.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.base/share/classes/sun/misc/Unsafe.java Thu Jan 14 20:57:33 2016 -0800
@@ -25,14 +25,13 @@
package sun.misc;
-import java.lang.reflect.Field;
-import java.security.ProtectionDomain;
-
+import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.misc.VM;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
-import jdk.internal.HotSpotIntrinsicCandidate;
-import jdk.internal.misc.VM;
+import java.lang.reflect.Field;
+import java.security.ProtectionDomain;
/**
@@ -1036,9 +1035,4 @@
private static void throwIllegalAccessError() {
throw new IllegalAccessError();
}
-
- // JVM interface methods
- private native boolean unalignedAccess0();
- private native boolean isBigEndian0();
-
}
--- a/jdk/src/java.base/share/native/include/jvm.h Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.base/share/native/include/jvm.h Thu Jan 14 20:57:33 2016 -0800
@@ -208,6 +208,9 @@
JNIEXPORT void JNICALL
JVM_SetMethodInfo(JNIEnv* env, jobject frame);
+JNIEXPORT jobjectArray JNICALL
+JVM_GetVmArguments(JNIEnv *env);
+
/*
* java.lang.Thread
*/
--- a/jdk/src/java.base/share/native/libjava/jni_util.c Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.base/share/native/libjava/jni_util.c Thu Jan 14 20:57:33 2016 -0800
@@ -660,7 +660,8 @@
*/
if ((strcmp(encname, "8859_1") == 0) ||
(strcmp(encname, "ISO8859-1") == 0) ||
- (strcmp(encname, "ISO8859_1") == 0))
+ (strcmp(encname, "ISO8859_1") == 0) ||
+ (strcmp(encname, "ISO-8859-1") == 0))
fastEncoding = FAST_8859_1;
else if (strcmp(encname, "ISO646-US") == 0)
fastEncoding = FAST_646_US;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/unix/conf/ppc64le/jvm.cfg Thu Jan 14 20:57:33 2016 -0800
@@ -0,0 +1,34 @@
+# 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.
+#
+# List of JVMs that can be used as an option to java, javac, etc.
+# Order is important -- first in this list is the default JVM.
+# NOTE that this both this file and its format are UNSUPPORTED and
+# WILL GO AWAY in a future release.
+#
+# You may also select a JVM in an arbitrary location with the
+# "-XXaltjvm=<jvm_dir>" option, but that too is unsupported
+# and may not be available in a future release.
+#
+-server KNOWN
+-client IGNORE
--- a/jdk/src/java.management/share/classes/javax/management/loading/MLetParser.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.management/share/classes/javax/management/loading/MLetParser.java Thu Jan 14 20:57:33 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -37,6 +37,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
@@ -142,7 +143,7 @@
skipSpace(in);
val = buf.toString();
}
- atts.put(att.toLowerCase(), val);
+ atts.put(att.toLowerCase(Locale.ENGLISH), val);
skipSpace(in);
}
return atts;
--- a/jdk/src/java.management/share/classes/javax/management/modelmbean/DescriptorSupport.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.management/share/classes/javax/management/modelmbean/DescriptorSupport.java Thu Jan 14 20:57:33 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -45,6 +45,7 @@
import java.security.AccessController;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
@@ -283,7 +284,7 @@
throw new RuntimeOperationsException(iae, msg);
}
- final String lowerInStr = inStr.toLowerCase();
+ final String lowerInStr = inStr.toLowerCase(Locale.ENGLISH);
if (!lowerInStr.startsWith("<descriptor>")
|| !lowerInStr.endsWith("</descriptor>")) {
throw new XMLParseException("No <descriptor>, </descriptor> pair");
--- a/jdk/src/java.management/share/classes/javax/management/remote/JMXServiceURL.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.management/share/classes/javax/management/remote/JMXServiceURL.java Thu Jan 14 20:57:33 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -38,6 +38,7 @@
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.util.BitSet;
+import java.util.Locale;
import java.util.StringTokenizer;
/**
@@ -168,7 +169,7 @@
final int protoStart = requiredPrefixLength;
final int protoEnd = indexOf(serviceURL, ':', protoStart);
this.protocol =
- serviceURL.substring(protoStart, protoEnd).toLowerCase();
+ serviceURL.substring(protoStart, protoEnd).toLowerCase(Locale.ENGLISH);
if (!serviceURL.regionMatches(protoEnd, "://", 0, 3)) {
throw new MalformedURLException("Missing \"://\" after " +
@@ -328,7 +329,7 @@
throw new MalformedURLException("More than one [[...]]");
}
- this.protocol = protocol.toLowerCase();
+ this.protocol = protocol.toLowerCase(Locale.ENGLISH);
this.host = host;
this.port = port;
--- a/jdk/src/java.management/share/classes/sun/management/jmxremote/ConnectorBootstrap.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.management/share/classes/sun/management/jmxremote/ConnectorBootstrap.java Thu Jan 14 20:57:33 2016 -0800
@@ -30,9 +30,12 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.Serializable;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.MalformedURLException;
+import java.net.Socket;
+import java.net.ServerSocket;
import java.net.UnknownHostException;
import java.rmi.NoSuchObjectException;
import java.rmi.Remote;
@@ -40,6 +43,7 @@
import java.rmi.registry.Registry;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.RMISocketFactory;
import java.rmi.server.RemoteObject;
import java.rmi.server.UnicastRemoteObject;
import java.security.KeyStore;
@@ -60,6 +64,8 @@
import javax.management.remote.rmi.RMIConnectorServer;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;
@@ -107,6 +113,8 @@
public static final String PORT =
"com.sun.management.jmxremote.port";
+ public static final String HOST =
+ "com.sun.management.jmxremote.host";
public static final String RMI_PORT =
"com.sun.management.jmxremote.rmi.port";
public static final String CONFIG_FILE_NAME =
@@ -424,10 +432,14 @@
checkAccessFile(accessFileName);
}
+ final String bindAddress =
+ props.getProperty(PropertyNames.HOST);
+
if (log.debugOn()) {
log.debug("startRemoteConnectorServer",
Agent.getText("jmxremote.ConnectorBootstrap.starting") +
"\n\t" + PropertyNames.PORT + "=" + port +
+ (bindAddress == null ? "" : "\n\t" + PropertyNames.HOST + "=" + bindAddress) +
"\n\t" + PropertyNames.RMI_PORT + "=" + rmiPort +
"\n\t" + PropertyNames.USE_SSL + "=" + useSsl +
"\n\t" + PropertyNames.USE_REGISTRY_SSL + "=" + useRegistrySsl +
@@ -458,7 +470,7 @@
sslConfigFileName, enabledCipherSuitesList,
enabledProtocolsList, sslNeedClientAuth,
useAuthentication, loginConfigName,
- passwordFileName, accessFileName);
+ passwordFileName, accessFileName, bindAddress);
cs = data.jmxConnectorServer;
url = data.jmxRemoteURL;
log.config("startRemoteConnectorServer",
@@ -628,12 +640,13 @@
String sslConfigFileName,
String[] enabledCipherSuites,
String[] enabledProtocols,
- boolean sslNeedClientAuth) {
+ boolean sslNeedClientAuth,
+ String bindAddress) {
if (sslConfigFileName == null) {
- return new SslRMIServerSocketFactory(
+ return new HostAwareSslSocketFactory(
enabledCipherSuites,
enabledProtocols,
- sslNeedClientAuth);
+ sslNeedClientAuth, bindAddress);
} else {
checkRestrictedFile(sslConfigFileName);
try {
@@ -687,11 +700,11 @@
SSLContext ctx = SSLContext.getInstance("SSL");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
- return new SslRMIServerSocketFactory(
+ return new HostAwareSslSocketFactory(
ctx,
enabledCipherSuites,
enabledProtocols,
- sslNeedClientAuth);
+ sslNeedClientAuth, bindAddress);
} catch (Exception e) {
throw new AgentConfigurationError(AGENT_EXCEPTION, e, e.toString());
}
@@ -711,7 +724,8 @@
boolean useAuthentication,
String loginConfigName,
String passwordFileName,
- String accessFileName)
+ String accessFileName,
+ String bindAddress)
throws IOException, MalformedURLException {
/* Make sure we use non-guessable RMI object IDs. Otherwise
@@ -719,7 +733,7 @@
* IDs. */
System.setProperty("java.rmi.server.randomIDs", "true");
- JMXServiceURL url = new JMXServiceURL("rmi", null, rmiPort);
+ JMXServiceURL url = new JMXServiceURL("rmi", bindAddress, rmiPort);
Map<String, Object> env = new HashMap<>();
@@ -727,6 +741,8 @@
env.put(RMIExporter.EXPORTER_ATTRIBUTE, exporter);
+ boolean useSocketFactory = bindAddress != null && !useSsl;
+
if (useAuthentication) {
if (loginConfigName != null) {
env.put("jmx.remote.x.login.config", loginConfigName);
@@ -751,7 +767,7 @@
csf = new SslRMIClientSocketFactory();
ssf = createSslRMIServerSocketFactory(
sslConfigFileName, enabledCipherSuites,
- enabledProtocols, sslNeedClientAuth);
+ enabledProtocols, sslNeedClientAuth, bindAddress);
}
if (useSsl) {
@@ -761,6 +777,12 @@
ssf);
}
+ if (useSocketFactory) {
+ ssf = new HostAwareSocketFactory(bindAddress);
+ env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,
+ ssf);
+ }
+
JMXConnectorServer connServer = null;
try {
connServer =
@@ -780,6 +802,10 @@
registry =
new SingleEntryRegistry(port, csf, ssf,
"jmxrmi", exporter.firstExported);
+ } else if (useSocketFactory) {
+ registry =
+ new SingleEntryRegistry(port, csf, ssf,
+ "jmxrmi", exporter.firstExported);
} else {
registry =
new SingleEntryRegistry(port,
@@ -813,4 +839,172 @@
private static final ClassLogger log =
new ClassLogger(ConnectorBootstrap.class.getPackage().getName(),
"ConnectorBootstrap");
+
+ private static class HostAwareSocketFactory implements RMIServerSocketFactory {
+
+ private final String bindAddress;
+
+ private HostAwareSocketFactory(String bindAddress) {
+ this.bindAddress = bindAddress;
+ }
+
+ @Override
+ public ServerSocket createServerSocket(int port) throws IOException {
+ if (bindAddress == null) {
+ return new ServerSocket(port);
+ } else {
+ try {
+ InetAddress addr = InetAddress.getByName(bindAddress);
+ return new ServerSocket(port, 0, addr);
+ } catch (UnknownHostException e) {
+ return new ServerSocket(port);
+ }
+ }
+ }
+ }
+
+ private static class HostAwareSslSocketFactory extends SslRMIServerSocketFactory {
+
+ private final String bindAddress;
+ private final String[] enabledCipherSuites;
+ private final String[] enabledProtocols;
+ private final boolean needClientAuth;
+ private final SSLContext context;
+
+ private HostAwareSslSocketFactory(String[] enabledCipherSuites,
+ String[] enabledProtocols,
+ boolean sslNeedClientAuth,
+ String bindAddress) throws IllegalArgumentException {
+ this(null, enabledCipherSuites, enabledProtocols, sslNeedClientAuth, bindAddress);
+ }
+
+ private HostAwareSslSocketFactory(SSLContext ctx,
+ String[] enabledCipherSuites,
+ String[] enabledProtocols,
+ boolean sslNeedClientAuth,
+ String bindAddress) throws IllegalArgumentException {
+ this.context = ctx;
+ this.bindAddress = bindAddress;
+ this.enabledProtocols = enabledProtocols;
+ this.enabledCipherSuites = enabledCipherSuites;
+ this.needClientAuth = sslNeedClientAuth;
+ checkValues(ctx, enabledCipherSuites, enabledProtocols);
+ }
+
+ @Override
+ public ServerSocket createServerSocket(int port) throws IOException {
+ if (bindAddress != null) {
+ try {
+ InetAddress addr = InetAddress.getByName(bindAddress);
+ return new SslServerSocket(port, 0, addr, context,
+ enabledCipherSuites, enabledProtocols, needClientAuth);
+ } catch (UnknownHostException e) {
+ return new SslServerSocket(port, context,
+ enabledCipherSuites, enabledProtocols, needClientAuth);
+ }
+ } else {
+ return new SslServerSocket(port, context,
+ enabledCipherSuites, enabledProtocols, needClientAuth);
+ }
+ }
+
+ private static void checkValues(SSLContext context,
+ String[] enabledCipherSuites,
+ String[] enabledProtocols) throws IllegalArgumentException {
+ // Force the initialization of the default at construction time,
+ // rather than delaying it to the first time createServerSocket()
+ // is called.
+ //
+ final SSLSocketFactory sslSocketFactory =
+ context == null ?
+ (SSLSocketFactory)SSLSocketFactory.getDefault() : context.getSocketFactory();
+ SSLSocket sslSocket = null;
+ if (enabledCipherSuites != null || enabledProtocols != null) {
+ try {
+ sslSocket = (SSLSocket) sslSocketFactory.createSocket();
+ } catch (Exception e) {
+ final String msg = "Unable to check if the cipher suites " +
+ "and protocols to enable are supported";
+ throw (IllegalArgumentException)
+ new IllegalArgumentException(msg).initCause(e);
+ }
+ }
+
+ // Check if all the cipher suites and protocol versions to enable
+ // are supported by the underlying SSL/TLS implementation and if
+ // true create lists from arrays.
+ //
+ if (enabledCipherSuites != null) {
+ sslSocket.setEnabledCipherSuites(enabledCipherSuites);
+ }
+ if (enabledProtocols != null) {
+ sslSocket.setEnabledProtocols(enabledProtocols);
+ }
+ }
+ }
+
+ private static class SslServerSocket extends ServerSocket {
+
+ private static SSLSocketFactory defaultSSLSocketFactory;
+ private final String[] enabledCipherSuites;
+ private final String[] enabledProtocols;
+ private final boolean needClientAuth;
+ private final SSLContext context;
+
+ private SslServerSocket(int port,
+ SSLContext ctx,
+ String[] enabledCipherSuites,
+ String[] enabledProtocols,
+ boolean needClientAuth) throws IOException {
+ super(port);
+ this.enabledProtocols = enabledProtocols;
+ this.enabledCipherSuites = enabledCipherSuites;
+ this.needClientAuth = needClientAuth;
+ this.context = ctx;
+ }
+
+ private SslServerSocket(int port,
+ int backlog,
+ InetAddress bindAddr,
+ SSLContext ctx,
+ String[] enabledCipherSuites,
+ String[] enabledProtocols,
+ boolean needClientAuth) throws IOException {
+ super(port, backlog, bindAddr);
+ this.enabledProtocols = enabledProtocols;
+ this.enabledCipherSuites = enabledCipherSuites;
+ this.needClientAuth = needClientAuth;
+ this.context = ctx;
+ }
+
+ @Override
+ public Socket accept() throws IOException {
+ final SSLSocketFactory sslSocketFactory =
+ context == null ?
+ getDefaultSSLSocketFactory() : context.getSocketFactory();
+ Socket socket = super.accept();
+ SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(
+ socket, socket.getInetAddress().getHostName(),
+ socket.getPort(), true);
+ sslSocket.setUseClientMode(false);
+ if (enabledCipherSuites != null) {
+ sslSocket.setEnabledCipherSuites(enabledCipherSuites);
+ }
+ if (enabledProtocols != null) {
+ sslSocket.setEnabledProtocols(enabledProtocols);
+ }
+ sslSocket.setNeedClientAuth(needClientAuth);
+ return sslSocket;
+ }
+
+ private static synchronized SSLSocketFactory getDefaultSSLSocketFactory() {
+ if (defaultSSLSocketFactory == null) {
+ defaultSSLSocketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
+ return defaultSSLSocketFactory;
+ } else {
+ return defaultSSLSocketFactory;
+ }
+ }
+
+ }
}
--- a/jdk/src/java.management/share/conf/management.properties Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.management/share/conf/management.properties Thu Jan 14 20:57:33 2016 -0800
@@ -316,3 +316,16 @@
# For a non-default password file location use the following line
# com.sun.management.jmxremote.access.file=filepath
+#
+
+# ################ Management agent listen interface #########################
+#
+# com.sun.management.jmxremote.host=<host-or-interface-name>
+# Specifies the local interface on which the JMX RMI agent will bind.
+# This is useful when running on machines which have several
+# interfaces defined. It makes it possible to listen to a specific
+# subnet accessible through that interface.
+#
+# The format of the value for that property is any string accepted
+# by java.net.InetAddress.getByName(String).
+#
--- a/jdk/src/java.management/share/native/include/jmm.h Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.management/share/native/include/jmm.h Thu Jan 14 20:57:33 2016 -0800
@@ -227,16 +227,10 @@
jint (JNICALL *GetOptionalSupport) (JNIEnv *env,
jmmOptionalSupport* support_ptr);
- /* This is used by JDK 6 and earlier.
- * For JDK 7 and after, use GetInputArgumentArray.
- */
- jobject (JNICALL *GetInputArguments) (JNIEnv *env);
-
jint (JNICALL *GetThreadInfo) (JNIEnv *env,
jlongArray ids,
jint maxDepth,
jobjectArray infoArray);
- jobjectArray (JNICALL *GetInputArgumentArray) (JNIEnv *env);
jobjectArray (JNICALL *GetMemoryPools) (JNIEnv* env, jobject mgr);
--- a/jdk/src/java.management/share/native/libmanagement/VMManagementImpl.c Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/java.management/share/native/libmanagement/VMManagementImpl.c Thu Jan 14 20:57:33 2016 -0800
@@ -112,7 +112,7 @@
Java_sun_management_VMManagementImpl_getVmArguments0
(JNIEnv *env, jobject dummy)
{
- return jmm_interface->GetInputArgumentArray(env);
+ return JVM_GetVmArguments(env);
}
JNIEXPORT jlong JNICALL
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/EventRequestManagerImpl.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/EventRequestManagerImpl.java Thu Jan 14 20:57:33 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -43,7 +43,7 @@
class EventRequestManagerImpl extends MirrorImpl
implements EventRequestManager
{
- List<? extends EventRequest>[] requestLists;
+ private final List<? extends EventRequest>[] requestLists;
private static int methodExitEventCmd = 0;
static int JDWPtoJDISuspendPolicy(byte jdwpPolicy) {
@@ -83,7 +83,7 @@
return System.identityHashCode(this);
}
- abstract class EventRequestImpl extends MirrorImpl implements EventRequest {
+ private abstract class EventRequestImpl extends MirrorImpl implements EventRequest {
int id;
/*
@@ -734,7 +734,7 @@
}
requestLists = new List[highest+1];
for (int i=0; i <= highest; i++) {
- requestLists[i] = new ArrayList<>();
+ requestLists[i] = Collections.synchronizedList(new ArrayList<>());
}
}
@@ -933,22 +933,27 @@
}
List<? extends EventRequest> unmodifiableRequestList(int eventCmd) {
- return Collections.unmodifiableList(requestList(eventCmd));
+ // No need of explicit synchronization for requestList here.
+ // It is taken care internally by SynchronizedList class.
+ return Collections.unmodifiableList(new ArrayList<>(requestList(eventCmd)));
}
EventRequest request(int eventCmd, int requestId) {
List<? extends EventRequest> rl = requestList(eventCmd);
- for (int i = rl.size() - 1; i >= 0; i--) {
- EventRequestImpl er = (EventRequestImpl)rl.get(i);
- if (er.id == requestId) {
- return er;
+ synchronized(rl) { // Refer Collections.synchronizedList javadoc.
+ Iterator<? extends EventRequest> itr = rl.iterator();
+ while (itr.hasNext()){
+ EventRequestImpl er = (EventRequestImpl)itr.next();
+ if (er.id == requestId)
+ return er;
}
}
return null;
}
- List<? extends EventRequest> requestList(int eventCmd) {
+ private List<? extends EventRequest> requestList(int eventCmd) {
return requestLists[eventCmd];
}
}
+
--- a/jdk/test/com/sun/jdi/BreakpointWithFullGC.sh Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/test/com/sun/jdi/BreakpointWithFullGC.sh Thu Jan 14 20:57:33 2016 -0800
@@ -121,7 +121,8 @@
jdbFailIfNotPresent 'System\..*end of test'
# make sure we had at least one full GC
-debuggeeFailIfNotPresent 'Full GC'
+# Prior to JDK9-B95, the pattern was 'Full GC'
+debuggeeMatchRegexp '^.*?\bPause Full\b\(System.gc\(\)\)\b.*?$'
# check for error message due to thread ID change
debuggeeFailIfPresent \
--- a/jdk/test/com/sun/management/HotSpotDiagnosticMXBean/CheckOrigin.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/test/com/sun/management/HotSpotDiagnosticMXBean/CheckOrigin.java Thu Jan 14 20:57:33 2016 -0800
@@ -62,7 +62,7 @@
ProcessBuilder pb = ProcessTools.
createJavaProcessBuilder(
"-XX:+UseConcMarkSweepGC", // this will cause UseParNewGC to be FLAG_SET_ERGO
- "-XX:+PrintGCDetails",
+ "-XX:+UseCodeAging",
"-XX:+UseCerealGC", // Should be ignored.
"-XX:Flags=" + flagsFile.getAbsolutePath(),
"-cp", System.getProperty("test.class.path"),
@@ -97,7 +97,7 @@
// Not set, so should be default
checkOrigin("ManagementServer", Origin.DEFAULT);
// Set on the command line
- checkOrigin("PrintGCDetails", Origin.VM_CREATION);
+ checkOrigin("UseCodeAging", Origin.VM_CREATION);
// Set in _JAVA_OPTIONS
checkOrigin("TraceExceptions", Origin.ENVIRON_VAR);
// Set in JAVA_TOOL_OPTIONS
--- a/jdk/test/com/sun/management/HotSpotDiagnosticMXBean/GetVMOption.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/test/com/sun/management/HotSpotDiagnosticMXBean/GetVMOption.java Thu Jan 14 20:57:33 2016 -0800
@@ -28,7 +28,7 @@
* @author Mandy Chung
*
* @modules jdk.management
- * @run main/othervm -XX:+PrintGCDetails GetVMOption
+ * @run main/othervm -XX:+HeapDumpOnOutOfMemoryError GetVMOption
*/
import com.sun.management.HotSpotDiagnosticMXBean;
@@ -38,7 +38,7 @@
import javax.management.MBeanServer;
public class GetVMOption {
- private static final String PRINT_GC_DETAILS = "PrintGCDetails";
+ private static final String HEAP_DUMP_ON_OOM = "HeapDumpOnOutOfMemoryError";
private static final String EXPECTED_VALUE = "true";
private static final String BAD_OPTION = "BadOption";
private static final String HOTSPOT_DIAGNOSTIC_MXBEAN_NAME =
@@ -58,7 +58,7 @@
}
private static void checkVMOption(HotSpotDiagnosticMXBean mbean) {
- VMOption option = mbean.getVMOption(PRINT_GC_DETAILS);
+ VMOption option = mbean.getVMOption(HEAP_DUMP_ON_OOM);
if (!option.getValue().equalsIgnoreCase(EXPECTED_VALUE)) {
throw new RuntimeException("Unexpected value: " +
option.getValue() + " expected: " + EXPECTED_VALUE);
--- a/jdk/test/com/sun/management/HotSpotDiagnosticMXBean/SetVMOption.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/test/com/sun/management/HotSpotDiagnosticMXBean/SetVMOption.java Thu Jan 14 20:57:33 2016 -0800
@@ -30,7 +30,7 @@
* @author Jaroslav Bachorik
*
* @modules jdk.management
- * @run main/othervm -XX:+PrintGCDetails SetVMOption
+ * @run main/othervm -XX:+HeapDumpOnOutOfMemoryError SetVMOption
*/
import java.lang.management.ManagementFactory;
@@ -40,7 +40,7 @@
import com.sun.management.VMOption.Origin;
public class SetVMOption {
- private static final String PRINT_GC_DETAILS = "PrintGCDetails";
+ private static final String HEAP_DUMP_ON_OOM = "HeapDumpOnOutOfMemoryError";
private static final String EXPECTED_VALUE = "true";
private static final String BAD_VALUE = "yes";
private static final String NEW_VALUE = "false";
@@ -51,7 +51,7 @@
mbean =
ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
- VMOption option = findPrintGCDetailsOption();
+ VMOption option = findHeapDumpOnOomOption();
if (!option.getValue().equalsIgnoreCase(EXPECTED_VALUE)) {
throw new RuntimeException("Unexpected value: " +
option.getValue() + " expected: " + EXPECTED_VALUE);
@@ -61,14 +61,14 @@
option.getOrigin() + " expected: VM_CREATION");
}
if (!option.isWriteable()) {
- throw new RuntimeException("Expected " + PRINT_GC_DETAILS +
+ throw new RuntimeException("Expected " + HEAP_DUMP_ON_OOM +
" to be writeable");
}
// set VM option to a new value
- mbean.setVMOption(PRINT_GC_DETAILS, NEW_VALUE);
+ mbean.setVMOption(HEAP_DUMP_ON_OOM, NEW_VALUE);
- option = findPrintGCDetailsOption();
+ option = findHeapDumpOnOomOption();
if (!option.getValue().equalsIgnoreCase(NEW_VALUE)) {
throw new RuntimeException("Unexpected value: " +
option.getValue() + " expected: " + NEW_VALUE);
@@ -77,7 +77,7 @@
throw new RuntimeException("Unexpected origin: " +
option.getOrigin() + " expected: MANAGEMENT");
}
- VMOption o = mbean.getVMOption(PRINT_GC_DETAILS);
+ VMOption o = mbean.getVMOption(HEAP_DUMP_ON_OOM);
if (!option.getValue().equals(o.getValue())) {
throw new RuntimeException("Unmatched value: " +
option.getValue() + " expected: " + o.getValue());
@@ -123,17 +123,17 @@
}
}
- public static VMOption findPrintGCDetailsOption() {
+ public static VMOption findHeapDumpOnOomOption() {
List<VMOption> options = mbean.getDiagnosticOptions();
VMOption gcDetails = null;
for (VMOption o : options) {
- if (o.getName().equals(PRINT_GC_DETAILS)) {
+ if (o.getName().equals(HEAP_DUMP_ON_OOM)) {
gcDetails = o;
break;
}
}
if (gcDetails == null) {
- throw new RuntimeException("VM option " + PRINT_GC_DETAILS +
+ throw new RuntimeException("VM option " + HEAP_DUMP_ON_OOM +
" not found");
}
return gcDetails;
--- a/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest.java Thu Jan 14 20:57:33 2016 -0800
@@ -100,7 +100,7 @@
opts.addAll(Arrays.asList(Utils.getTestJavaOpts()));
opts.add("-cp");
opts.add(System.getProperty("test.class.path", "test.class.path"));
- opts.add("-XX:+PrintGCDetails");
+ opts.add("-Xlog:gc*=debug");
opts.addAll(Arrays.asList(testOpts));
opts.add(classMain);
--- a/jdk/test/java/lang/management/MemoryMXBean/RunUtil.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/test/java/lang/management/MemoryMXBean/RunUtil.java Thu Jan 14 20:57:33 2016 -0800
@@ -66,7 +66,7 @@
opts.addAll(Arrays.asList(Utils.getTestJavaOpts()));
opts.add("-cp");
opts.add(System.getProperty("test.class.path", "test.class.path"));
- opts.add("-XX:+PrintGCDetails");
+ opts.add("-Xlog:gc*=debug");
if (clearGcOpts) {
opts = Utils.removeGcOpts(opts);
--- a/jdk/test/java/lang/management/RuntimeMXBean/TestInputArgument.sh Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/test/java/lang/management/RuntimeMXBean/TestInputArgument.sh Thu Jan 14 20:57:33 2016 -0800
@@ -48,8 +48,8 @@
runOne InputArgument
-runOne -XX:+UseFastJNIAccessors -XX:+PrintGCDetails InputArgument -XX:+PrintGCDetails
-runOne -XX:+UseFastJNIAccessors -XX:+PrintGCDetails InputArgument -XX:+UseFastJNIAccessors
+runOne -XX:+UseFastJNIAccessors -Xlog:gc*=debug InputArgument
+runOne -XX:+UseFastJNIAccessors -Xlog:gc*=debug InputArgument -XX:+UseFastJNIAccessors
runOne "-Dprops=one two three" InputArgument "-Dprops=one two three"
exit 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/ref/PhantomReferentClearing.java Thu Jan 14 20:57:33 2016 -0800
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8071507
+ * @summary Test that PhantomReferences are cleared when notified.
+ * @run main/othervm PhantomReferentClearing
+ */
+
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.util.ArrayList;
+import java.util.List;
+
+public class PhantomReferentClearing {
+
+ private static final long ENQUEUE_TIMEOUT = 1000; // 1 sec, in millis
+
+ // P1 & P2 are PhantomReference objects
+ // O1 & O2 are objects
+ //
+ // -> is a strong reference
+ // => is a referent reference
+ //
+ // root -> P1
+ // root -> P2
+ // root -> O1
+ // root -> O2
+ // O1 -> O2
+ // P1 => O1
+ // P2 => O2
+ //
+ // (1) Remove root -> O1 and collect. P1 notified, P2 !notified.
+ // (2) Remove root -> O2 and collect.
+ //
+ // If phantom references are cleared when notified, as proposed by
+ // 8071507, then P2 should be notified, and the test passes.
+ //
+ // Otherwise, P2 does not get notified because it remains reachable
+ // from O1, which is being retained by P1. This fails the test.
+
+ private static final ReferenceQueue<Object> Q1 = new ReferenceQueue<>();
+ private static final ReferenceQueue<Object> Q2 = new ReferenceQueue<>();
+
+ private static volatile Object O2 = new Object();
+ private static volatile List<Object> O1 = new ArrayList<>();
+ static {
+ O1.add(O2);
+ }
+
+ private static final PhantomReference<Object> P1 = new PhantomReference<>(O1, Q1);
+ private static final PhantomReference<Object> P2 = new PhantomReference<>(O2, Q2);
+
+ public static void main(String[] args) throws InterruptedException {
+
+ // Collect, and verify neither P1 or P2 notified.
+ System.gc();
+ if (Q1.remove(ENQUEUE_TIMEOUT) != null) {
+ throw new RuntimeException("P1 already notified");
+ } else if (Q2.poll() != null) {
+ throw new RuntimeException("P2 already notified");
+ }
+
+ // Delete root -> O1, collect, verify P1 notified, P2 not notified.
+ O1 = null;
+ System.gc();
+ if (Q1.remove(ENQUEUE_TIMEOUT) == null) {
+ throw new RuntimeException("P1 not notified by O1 deletion");
+ } else if (Q2.remove(ENQUEUE_TIMEOUT) != null) {
+ throw new RuntimeException("P2 notified by O1 deletion.");
+ }
+
+ // Delete root -> O2, collect. P2 should be notified.
+ O2 = null;
+ System.gc();
+ if (Q2.remove(ENQUEUE_TIMEOUT) == null) {
+ throw new RuntimeException("P2 not notified by O2 deletion");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/ref/ReachabilityFenceTest.java Thu Jan 14 20:57:33 2016 -0800
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8133348
+ * @summary Tests if reachabilityFence is working
+ *
+ * @run main/othervm -Xint -Dpremature=false ReachabilityFenceTest
+ * @run main/othervm -XX:TieredStopAtLevel=1 -Dpremature=true ReachabilityFenceTest
+ * @run main/othervm -XX:TieredStopAtLevel=2 -Dpremature=true ReachabilityFenceTest
+ * @run main/othervm -XX:TieredStopAtLevel=3 -Dpremature=true ReachabilityFenceTest
+ * @run main/othervm -XX:TieredStopAtLevel=4 -Dpremature=true ReachabilityFenceTest
+ */
+
+import java.lang.ref.Reference;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class ReachabilityFenceTest {
+
+ /*
+ * Implementation notes:
+ *
+ * This test has positive and negative parts.
+ *
+ * Negative test is "nonFenced", and it tests that absent of reachabilityFence, the object can
+ * be prematurely finalized -- this validates the test itself. Not every VM mode is expected to
+ * prematurely finalize the objects, and -Dpremature option communicates that to test. If a VM mode
+ * passes the negative test, then our understanding of what could happen is correct, and we can
+ * go forward.
+ *
+ * Positive test is "fenced", and it checks that given the reachabilityFence at the end of the block,
+ * the object cannot be finalized. There is no sense running a positive test when premature finalization
+ * is not expected. It is a job for negative test to verify that invariant.
+ *
+ * The test methods should be appropriately compiled, therefore we do several iterations.
+ */
+
+ // Enough to OSR and compile
+ static final int LOOP_ITERS = Integer.getInteger("LOOP_ITERS", 50000);
+
+ // Enough after which to start triggering GC and finalization
+ static final int WARMUP_LOOP_ITERS = LOOP_ITERS - Integer.getInteger("GC_ITERS", 100);
+
+ // Enough to switch from an OSR'ed method to compiled method
+ static final int MAIN_ITERS = 3;
+
+ static final boolean PREMATURE_FINALIZATION = Boolean.getBoolean("premature");
+
+ public static void main(String... args) {
+ // Negative test
+ boolean finalized = false;
+ for (int c = 0; !finalized && c < MAIN_ITERS; c++) {
+ finalized |= nonFenced();
+ }
+
+ if (PREMATURE_FINALIZATION && !finalized) {
+ throw new IllegalStateException("The object had never been finalized before timeout reached.");
+ }
+
+ if (!PREMATURE_FINALIZATION && finalized) {
+ throw new IllegalStateException("The object had been finalized without a fence, even though we don't expect it.");
+ }
+
+ if (!PREMATURE_FINALIZATION)
+ return;
+
+ // Positive test
+ finalized = false;
+ for (int c = 0; !finalized && c < MAIN_ITERS; c++) {
+ finalized |= fenced();
+ }
+
+ if (finalized) {
+ throw new IllegalStateException("The object had been prematurely finalized.");
+ }
+ }
+
+ public static boolean nonFenced() {
+ AtomicBoolean finalized = new AtomicBoolean();
+ MyFinalizeable o = new MyFinalizeable(finalized);
+
+ for (int i = 0; i < LOOP_ITERS; i++) {
+ if (finalized.get()) break;
+ if (i > WARMUP_LOOP_ITERS) {
+ System.gc();
+ System.runFinalization();
+ }
+ }
+
+ return finalized.get();
+ }
+
+ public static boolean fenced() {
+ AtomicBoolean finalized = new AtomicBoolean();
+ MyFinalizeable o = new MyFinalizeable(finalized);
+
+ for (int i = 0; i < LOOP_ITERS; i++) {
+ if (finalized.get()) break;
+ if (i > WARMUP_LOOP_ITERS) {
+ System.gc();
+ System.runFinalization();
+ }
+ }
+
+ Reference.reachabilityFence(o);
+
+ return finalized.get();
+ }
+
+ private static class MyFinalizeable {
+ private final AtomicBoolean finalized;
+
+ public MyFinalizeable(AtomicBoolean b) {
+ this.finalized = b;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ super.finalize();
+ finalized.set(true);
+ }
+ }
+}
\ No newline at end of file
--- a/jdk/test/java/text/Format/DecimalFormat/FormatMicroBenchmark.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/test/java/text/Format/DecimalFormat/FormatMicroBenchmark.java Thu Jan 14 20:57:33 2016 -0800
@@ -51,7 +51,7 @@
* getting reliable numbers. Otherwise GC activity may corrupt results.
* As of jdk80b48 using "-Xms500m -Xmx500m -XX:NewSize=400m" covers
* all cases.
- * - Optionally using "-XX:+printGC" option provides information that
+ * - Optionally using "-Xlog:gc" option provides information that
* helps checking any GC activity while benches are run.
*
* Vm Options:
@@ -60,7 +60,7 @@
* non fast-path case: -Xms500m -Xmx500m -XX:NewSize=400m
* or use worst case (non fast-path above) with both types of algorithm.
*
- * - use -XX:+PrintGC to verify memory consumption of the benchmarks.
+ * - use -Xlog:gc to verify memory consumption of the benchmarks.
* (See "Checking Memory Consumption" below).
*
* Description:
@@ -166,7 +166,7 @@
* but is not enough, since any unexpected incremental GC may lower
* artificially the estimation of the memory consumption.
*
- * Options to set are -Xms, -Xmx, -XX:NewSize, plus -XX:+PrintGC to evaluate
+ * Options to set are -Xms, -Xmx, -XX:NewSize, plus -Xlog:gc to evaluate
* correctly the values of these options. When running "-verbose", varying
* numbers reported for memory consumption may indicate bad choices for these
* options.
@@ -217,7 +217,7 @@
" getting reliable numbers. Otherwise GC activity may corrupt results.\n" +
" As of jdk80b48 using \"-Xms500m -Xmx500m -XX:NewSize=400m\" covers \n" +
" all cases.\n" +
- " - Optionally using \"-XX:+printGC\" option provides information that \n" +
+ " - Optionally using \"-Xlog:gc\" option provides information that \n" +
" helps checking any GC activity while benches are run.\n\n" +
"Look at the heading comments and description in source code for " +
"detailed information.\n");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/loading/MletParserLocaleTest.java Thu Jan 14 20:57:33 2016 -0800
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 7065236
+ * @summary Checking MletParser for Locale insensitive strings
+ * @author Harsha Wardhana B
+ * @modules java.management
+ * @run clean MletParserLocaleTest
+ * @run build MletParserLocaleTest
+ * @run main/othervm/timeout=5 MletParserLocaleTest mlet4.html
+ */
+
+import java.io.File;
+import java.util.Locale;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+import javax.management.loading.MLet;
+
+public class MletParserLocaleTest {
+
+ public static void main(String[] args) throws Exception {
+
+ boolean error = false;
+
+ // Instantiate the MBean server
+ //
+ System.out.println("Create the MBean server");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ // Get Default Locale
+ Locale loc = Locale.getDefault();
+
+ // Instantiate an MLet
+ //
+ System.out.println("Create the MLet");
+ MLet mlet = new MLet();
+
+ // Register the MLet MBean with the MBeanServer
+ //
+ System.out.println("Register the MLet MBean");
+ ObjectName mletObjectName = new ObjectName("Test:type=MLet");
+ mbs.registerMBean(mlet, mletObjectName);
+
+ // Call getMBeansFromURL
+ //
+ System.out.println("Call mlet.getMBeansFromURL(<url>)");
+ String testSrc = System.getProperty("test.src");
+ System.out.println("test.src = " + testSrc);
+ String urlCodebase;
+ if (testSrc.startsWith("/")) {
+ urlCodebase =
+ "file:" + testSrc.replace(File.separatorChar, '/') + "/";
+ } else {
+ urlCodebase =
+ "file:/" + testSrc.replace(File.separatorChar, '/') + "/";
+ }
+ String mletFile = urlCodebase + args[0];
+ System.out.println("MLet File = " + mletFile);
+ try {
+ // Change default Locale to Turkish
+ Locale.setDefault(new Locale("tr", "TR"));
+ mlet.getMBeansFromURL(mletFile);
+ System.out.println("Test Passes");
+ } catch (Exception e) {
+ error = true;
+ e.printStackTrace(System.out);
+ }finally {
+ Locale.setDefault(loc);
+ }
+
+ // Unregister the MLet MBean
+ //
+ System.out.println("Unregister the MLet MBean");
+ mbs.unregisterMBean(mletObjectName);
+
+ // Release MBean server
+ //
+ System.out.println("Release the MBean server");
+ MBeanServerFactory.releaseMBeanServer(mbs);
+
+ // End Test
+ //
+ System.out.println("Bye! Bye!");
+ if (error) System.exit(1);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/loading/mlet4.html Thu Jan 14 20:57:33 2016 -0800
@@ -0,0 +1,2 @@
+<MLET CODE=HelloWorld ARCHIVE="helloworld.jar">
+</MLET>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/modelmbean/DescriptorSupportXMLLocaleTest.java Thu Jan 14 20:57:33 2016 -0800
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 7065236
+ * @summary Test for locale insensitive strings in DescriptorSupport class
+ * @author Harsha Wardhana B
+ * @modules java.management
+ * @run clean DescriptorSupportXMLLocaleTest
+ * @run build DescriptorSupportXMLLocaleTest
+ * @run main DescriptorSupportXMLLocaleTest
+ */
+import java.util.Locale;
+import javax.management.modelmbean.DescriptorSupport;
+
+public class DescriptorSupportXMLLocaleTest {
+
+ public static void main(String[] args) throws Exception {
+ boolean failed = false;
+ String xmlDesc = "<DESCRIPTOR>"
+ + "<FIELD name=\"field1\" value=\"dummy\">"
+ + "</FIELD>"
+ + "</DESCRIPTOR>";
+ Locale loc = Locale.getDefault();
+ try {
+ Locale.setDefault(new Locale("tr", "TR"));
+ new DescriptorSupport(xmlDesc);
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ failed = true;
+ }finally{
+ Locale.setDefault(loc);
+ }
+
+ if (!failed) {
+ System.out.println("OK: all tests passed");
+ } else {
+ System.out.println("TEST FAILED");
+ throw new IllegalArgumentException("Test Failed");
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/remote/mandatory/connection/JMXServiceURLLocaleTest.java Thu Jan 14 20:57:33 2016 -0800
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 7065236
+ * @summary Test for locale insensitive strings in JMXServiceURL class
+ * @author Harsha Wardhana B
+ * @modules java.management
+ * @run clean JMXServiceURLLocaleTest
+ * @run build JMXServiceURLLocaleTest
+ * @run main JMXServiceURLLocaleTest
+*/
+
+import java.util.Locale;
+import javax.management.remote.JMXServiceURL;
+
+public class JMXServiceURLLocaleTest {
+ public static void main(String[] args) throws Exception {
+
+ boolean error = false;
+ Locale loc = Locale.getDefault();
+
+ try {
+ echo("Setting Turkish locale");
+ // Set locale other than Locale.ENGLISH
+ Locale.setDefault(new Locale("tr", "TR"));
+ new JMXServiceURL("service:jmx:RMI://");
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ error = true;
+ } finally {
+ Locale.setDefault(loc);
+ echo("\n>>> Bye! Bye!");
+ }
+
+ if (error) {
+ echo("\nTest failed! ");
+ throw new IllegalArgumentException("Test failed");
+ } else {
+ echo("\nTest passed!\n");
+ }
+ }
+
+ private static void echo(String msg) {
+ System.out.println(msg);
+ }
+}
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/JDKToolLauncher.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/JDKToolLauncher.java Thu Jan 14 20:57:33 2016 -0800
@@ -38,8 +38,7 @@
* <pre>
* {@code
* JDKToolLauncher jmap = JDKToolLauncher.create("jmap")
- * .addVMArg("-XX:+PrintGC");
- * .addVMArg("-XX:+PrintGCDetails")
+ * .addVMArg("-Xlog:gc*=debug")
* .addToolArg("-heap")
* .addToolArg(pid);
* ProcessBuilder pb = new ProcessBuilder(jmap.getCommand());
--- a/jdk/test/sun/invoke/anon/ConstantPoolPatch/OptimalMapSize.java Thu Jan 14 12:04:19 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 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.
- *
- * 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 8080535
- * @summary Static storages should be initialized with optimal capacity
- * @library /lib/testlibrary
- * @build jdk.testlibrary.OptimalCapacity
- * @run main OptimalMapSize
- */
-
-import jdk.testlibrary.OptimalCapacity;
-
-public class OptimalMapSize {
- public static void main(String[] args) throws Throwable {
- OptimalCapacity.ofIdentityHashMap(
- Class.forName("sun.invoke.anon.ConstantPoolPatch"),
- "CONSTANT_VALUE_CLASS_TAG", 6);
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/management/jmxremote/bootstrap/JMXAgentInterfaceBinding.java Thu Jan 14 20:57:33 2016 -0800
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2015, Red Hat Inc
+ * 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.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.rmi.RMIConnectorServer;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.rmi.ssl.SslRMIClientSocketFactory;
+
+/**
+ * Tests client connections to the JDK's built-in JMX agent server on the given
+ * ports/interface combinations.
+ *
+ * @see JMXInterfaceBindingTest
+ *
+ * @author Severin Gehwolf <sgehwolf@redhat.com>
+ *
+ * Usage:
+ *
+ * SSL:
+ * java -Dcom.sun.management.jmxremote.ssl.need.client.auth=true \
+ * -Dcom.sun.management.jmxremote.host=127.0.0.1 \
+ * -Dcom.sun.management.jmxremote.port=9111 \
+ * -Dcom.sun.management.jmxremote.rmi.port=9112 \
+ * -Dcom.sun.management.jmxremote.authenticate=false \
+ * -Dcom.sun.management.jmxremote.ssl=true \
+ * -Dcom.sun.management.jmxremote.registry.ssl=true
+ * -Djavax.net.ssl.keyStore=... \
+ * -Djavax.net.ssl.keyStorePassword=... \
+ * JMXAgentInterfaceBinding 127.0.0.1 9111 9112 true
+ *
+ * Non-SSL:
+ * java -Dcom.sun.management.jmxremote.host=127.0.0.1 \
+ * -Dcom.sun.management.jmxremote.port=9111 \
+ * -Dcom.sun.management.jmxremote.rmi.port=9112 \
+ * -Dcom.sun.management.jmxremote.authenticate=false \
+ * -Dcom.sun.management.jmxremote.ssl=false \
+ * JMXAgentInterfaceBinding 127.0.0.1 9111 9112 false
+ *
+ */
+public class JMXAgentInterfaceBinding {
+
+ private final MainThread mainThread;
+
+ public JMXAgentInterfaceBinding(InetAddress bindAddress,
+ int jmxPort,
+ int rmiPort,
+ boolean useSSL) {
+ this.mainThread = new MainThread(bindAddress, jmxPort, rmiPort, useSSL);
+ }
+
+ public void startEndpoint() {
+ mainThread.start();
+ try {
+ mainThread.join();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Test failed", e);
+ }
+ if (mainThread.isFailed()) {
+ mainThread.rethrowException();
+ }
+ }
+
+ public static void main(String[] args) {
+ if (args.length != 4) {
+ throw new RuntimeException(
+ "Test failed. usage: java JMXInterfaceBindingTest <BIND_ADDRESS> <JMX_PORT> <RMI_PORT> {true|false}");
+ }
+ int jmxPort = parsePortFromString(args[1]);
+ int rmiPort = parsePortFromString(args[2]);
+ boolean useSSL = Boolean.parseBoolean(args[3]);
+ String strBindAddr = args[0];
+ System.out.println(
+ "DEBUG: Running test for triplet (hostname,jmxPort,rmiPort) = ("
+ + strBindAddr + "," + jmxPort + "," + rmiPort + "), useSSL = " + useSSL);
+ InetAddress bindAddress;
+ try {
+ bindAddress = InetAddress.getByName(args[0]);
+ } catch (UnknownHostException e) {
+ throw new RuntimeException("Test failed. Unknown ip: " + args[0]);
+ }
+ JMXAgentInterfaceBinding test = new JMXAgentInterfaceBinding(bindAddress,
+ jmxPort, rmiPort, useSSL);
+ test.startEndpoint(); // Expect for main test to terminate process
+ }
+
+ private static int parsePortFromString(String port) {
+ try {
+ return Integer.parseInt(port);
+ } catch (NumberFormatException e) {
+ throw new RuntimeException(
+ "Invalid port specified. Not an integer! Value was: "
+ + port);
+ }
+ }
+
+ private static class JMXConnectorThread extends Thread {
+
+ private final InetAddress addr;
+ private final int jmxPort;
+ private final int rmiPort;
+ private final boolean useSSL;
+ private final CountDownLatch latch;
+ private boolean failed;
+ private boolean jmxConnectWorked;
+ private boolean rmiConnectWorked;
+
+ private JMXConnectorThread(InetAddress addr,
+ int jmxPort,
+ int rmiPort,
+ boolean useSSL,
+ CountDownLatch latch) {
+ this.addr = addr;
+ this.jmxPort = jmxPort;
+ this.rmiPort = rmiPort;
+ this.latch = latch;
+ this.useSSL = useSSL;
+ }
+
+ @Override
+ public void run() {
+ try {
+ connect();
+ } catch (IOException e) {
+ failed = true;
+ }
+ }
+
+ private void connect() throws IOException {
+ System.out.println(
+ "JMXConnectorThread: Attempting JMX connection on: "
+ + addr.getHostAddress() + " on port " + jmxPort);
+ JMXServiceURL url;
+ try {
+ url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://"
+ + addr.getHostAddress() + ":" + jmxPort + "/jmxrmi");
+ } catch (MalformedURLException e) {
+ throw new RuntimeException("Test failed.", e);
+ }
+ Map<String, Object> env = new HashMap<>();
+ if (useSSL) {
+ SslRMIClientSocketFactory csf = new SslRMIClientSocketFactory();
+ env.put("com.sun.jndi.rmi.factory.socket", csf);
+ env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, csf);
+ }
+ // connect and immediately close
+ JMXConnector c = JMXConnectorFactory.connect(url, env);
+ c.close();
+ System.out.println("JMXConnectorThread: connection to JMX worked");
+ jmxConnectWorked = true;
+ checkRmiSocket();
+ latch.countDown(); // signal we are done.
+ }
+
+ private void checkRmiSocket() throws IOException {
+ Socket rmiConnection;
+ if (useSSL) {
+ rmiConnection = SSLSocketFactory.getDefault().createSocket();
+ } else {
+ rmiConnection = new Socket();
+ }
+ SocketAddress target = new InetSocketAddress(addr, rmiPort);
+ rmiConnection.connect(target);
+ if (useSSL) {
+ ((SSLSocket)rmiConnection).startHandshake();
+ }
+ System.out.println(
+ "JMXConnectorThread: connection to rmi socket worked host/port = "
+ + addr.getHostAddress() + "/" + rmiPort);
+ rmiConnectWorked = true;
+ // Closing the channel without sending any data will cause an
+ // java.io.EOFException on the server endpoint. We don't care about this
+ // though, since we only want to test if we can connect.
+ rmiConnection.close();
+ }
+
+ public boolean isFailed() {
+ return failed;
+ }
+
+ public boolean jmxConnectionWorked() {
+ return jmxConnectWorked;
+ }
+
+ public boolean rmiConnectionWorked() {
+ return rmiConnectWorked;
+ }
+ }
+
+ private static class MainThread extends Thread {
+
+ private static final int WAIT_FOR_JMX_AGENT_TIMEOUT_MS = 500;
+ private final InetAddress bindAddress;
+ private final int jmxPort;
+ private final int rmiPort;
+ private final boolean useSSL;
+ private boolean terminated = false;
+ private boolean jmxAgentStarted = false;
+ private Exception excptn;
+
+ private MainThread(InetAddress bindAddress, int jmxPort, int rmiPort, boolean useSSL) {
+ this.bindAddress = bindAddress;
+ this.jmxPort = jmxPort;
+ this.rmiPort = rmiPort;
+ this.useSSL = useSSL;
+ }
+
+ @Override
+ public void run() {
+ try {
+ waitUntilReadyForConnections();
+ // Do nothing, but wait for termination.
+ try {
+ while (!terminated) {
+ Thread.sleep(100);
+ }
+ } catch (InterruptedException e) { // ignore
+ }
+ System.out.println("MainThread: Thread stopped.");
+ } catch (Exception e) {
+ this.excptn = e;
+ }
+ }
+
+ private void waitUntilReadyForConnections() {
+ CountDownLatch latch = new CountDownLatch(1);
+ JMXConnectorThread connectionTester = new JMXConnectorThread(
+ bindAddress, jmxPort, rmiPort, useSSL, latch);
+ connectionTester.start();
+ boolean expired = false;
+ try {
+ expired = !latch.await(WAIT_FOR_JMX_AGENT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ System.out.println(
+ "MainThread: Finished waiting for JMX agent to become available: expired == "
+ + expired);
+ jmxAgentStarted = !expired;
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Test failed", e);
+ }
+ if (!jmxAgentStarted) {
+ throw new RuntimeException(
+ "Test failed. JMX server agents not becoming available.");
+ }
+ if (connectionTester.isFailed()
+ || !connectionTester.jmxConnectionWorked()
+ || !connectionTester.rmiConnectionWorked()) {
+ throw new RuntimeException(
+ "Test failed. JMX agent does not seem ready. See log output for details.");
+ }
+ // The main test expects this exact message being printed
+ System.out.println("MainThread: Ready for connections");
+ }
+
+ private boolean isFailed() {
+ return excptn != null;
+ }
+
+ private void rethrowException() throws RuntimeException {
+ throw new RuntimeException(excptn);
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java Thu Jan 14 20:57:33 2016 -0800
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2015, Red Hat Inc
+ * 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.File;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+
+import jdk.testlibrary.ProcessThread;
+import jdk.testlibrary.ProcessTools;
+
+/**
+ * NOTE:
+ * This test requires at least a setup similar to the following in
+ * /etc/hosts file (or the windows equivalent). I.e. it expects it to
+ * be multi-homed and not both being the loop-back interface.
+ * For example:
+ * ----->8-------- /etc/hosts ----------->8---
+ * 127.0.0.1 localhost
+ * 192.168.0.1 localhost
+ * ----->8-------- /etc/hosts ----------->8---
+ *
+ * @test
+ * @bug 6425769
+ * @summary Test JMX agent host address binding. Same ports but different
+ * interfaces to bind to (using plain sockets and SSL sockets).
+ *
+ * @modules java.management/sun.management
+ * java.management/sun.management.jmxremote
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.* JMXAgentInterfaceBinding
+ * @run main/timeout=5 JMXInterfaceBindingTest
+ */
+public class JMXInterfaceBindingTest {
+
+ public static final int COMMUNICATION_ERROR_EXIT_VAL = 1;
+ public static final int STOP_PROCESS_EXIT_VAL = 143;
+ public static final int JMX_PORT = 9111;
+ public static final int RMI_PORT = 9112;
+ public static final String READY_MSG = "MainThread: Ready for connections";
+ public static final String TEST_CLASS = JMXAgentInterfaceBinding.class.getSimpleName();
+ public static final String KEYSTORE_LOC = System.getProperty("test.src", ".") +
+ File.separator +
+ "ssl" +
+ File.separator +
+ "keystore";
+ public static final String TRUSTSTORE_LOC = System.getProperty("test.src", ".") +
+ File.separator +
+ "ssl" +
+ File.separator +
+ "truststore";
+ public static final String TEST_CLASSPATH = System.getProperty("test.classes", ".");
+
+ public void run(InetAddress[] addrs) {
+ System.out.println("DEBUG: Running tests with plain sockets.");
+ runTests(addrs, false);
+ System.out.println("DEBUG: Running tests with SSL sockets.");
+ runTests(addrs, true);
+ }
+
+ private void runTests(InetAddress[] addrs, boolean useSSL) {
+ ProcessThread[] jvms = new ProcessThread[addrs.length];
+ for (int i = 0; i < addrs.length; i++) {
+ System.out.println();
+ String msg = String.format("DEBUG: Launching java tester for triplet (HOSTNAME,JMX_PORT,RMI_PORT) == (%s,%d,%d)",
+ addrs[i].getHostAddress(),
+ JMX_PORT,
+ RMI_PORT);
+ System.out.println(msg);
+ jvms[i] = runJMXBindingTest(addrs[i], useSSL);
+ jvms[i].start();
+ System.out.println("DEBUG: Started " + (i + 1) + " Process(es).");
+ }
+ int failedProcesses = 0;
+ for (ProcessThread pt: jvms) {
+ try {
+ pt.stopProcess();
+ pt.join();
+ } catch (InterruptedException e) {
+ System.err.println("Failed to stop process: " + pt.getName());
+ throw new RuntimeException("Test failed", e);
+ }
+ int exitValue = pt.getOutput().getExitValue();
+ // If there is a communication error (the case we care about)
+ // we get a exit code of 1
+ if (exitValue == COMMUNICATION_ERROR_EXIT_VAL) {
+ // Failure case since the java processes should still be
+ // running.
+ System.err.println("Test FAILURE on " + pt.getName());
+ failedProcesses++;
+ } else if (exitValue == STOP_PROCESS_EXIT_VAL) {
+ System.out.println("DEBUG: OK. Spawned java process terminated with expected exit code of " + STOP_PROCESS_EXIT_VAL);
+ } else {
+ System.err.println("Test FAILURE on " + pt.getName() + " reason: Unexpected exit code => " + exitValue);
+ failedProcesses++;
+ }
+ }
+ if (failedProcesses > 0) {
+ throw new RuntimeException("Test FAILED. " + failedProcesses + " out of " + addrs.length + " process(es) failed to start the JMX agent.");
+ }
+ }
+
+ private ProcessThread runJMXBindingTest(InetAddress a, boolean useSSL) {
+ List<String> args = new ArrayList<>();
+ args.add("-classpath");
+ args.add(TEST_CLASSPATH);
+ args.add("-Dcom.sun.management.jmxremote.host=" + a.getHostAddress());
+ args.add("-Dcom.sun.management.jmxremote.port=" + JMX_PORT);
+ args.add("-Dcom.sun.management.jmxremote.rmi.port=" + RMI_PORT);
+ args.add("-Dcom.sun.management.jmxremote.authenticate=false");
+ args.add("-Dcom.sun.management.jmxremote.ssl=" + Boolean.toString(useSSL));
+ if (useSSL) {
+ args.add("-Dcom.sun.management.jmxremote.registry.ssl=true");
+ args.add("-Djavax.net.ssl.keyStore=" + KEYSTORE_LOC);
+ args.add("-Djavax.net.ssl.trustStore=" + TRUSTSTORE_LOC);
+ args.add("-Djavax.net.ssl.keyStorePassword=password");
+ args.add("-Djavax.net.ssl.trustStorePassword=trustword");
+ }
+ args.add(TEST_CLASS);
+ args.add(a.getHostAddress());
+ args.add(Integer.toString(JMX_PORT));
+ args.add(Integer.toString(RMI_PORT));
+ args.add(Boolean.toString(useSSL));
+ try {
+ ProcessBuilder builder = ProcessTools.createJavaProcessBuilder(args.toArray(new String[] {}));
+ System.out.println(ProcessTools.getCommandLine(builder));
+ ProcessThread jvm = new ProcessThread("JMX-Tester-" + a.getHostAddress(), JMXInterfaceBindingTest::isJMXAgentResponseAvailable, builder);
+ return jvm;
+ } catch (Exception e) {
+ throw new RuntimeException("Test failed", e);
+ }
+
+ }
+
+ private static boolean isJMXAgentResponseAvailable(String line) {
+ if (line.equals(READY_MSG)) {
+ System.out.println("DEBUG: Found expected READY_MSG.");
+ return true;
+ } else if (line.startsWith("Error:")) {
+ // Allow for a JVM process that exits with
+ // "Error: JMX connector server communication error: ..."
+ // to continue as well since we handle that case elsewhere.
+ // This has the effect that the test does not timeout and
+ // fails with an exception in the test.
+ System.err.println("PROBLEM: JMX agent of target JVM did not start as it should.");
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static void main(String[] args) {
+ InetAddress[] addrs = getAddressesForLocalHost();
+ if (addrs.length < 2) {
+ System.out.println("Ignoring manual test since no more than one IPs are configured for 'localhost'");
+ return;
+ }
+ JMXInterfaceBindingTest test = new JMXInterfaceBindingTest();
+ test.run(addrs);
+ System.out.println("All tests PASSED.");
+ }
+
+ private static InetAddress[] getAddressesForLocalHost() {
+ InetAddress[] addrs;
+ try {
+ addrs = InetAddress.getAllByName("localhost");
+ } catch (UnknownHostException e) {
+ throw new RuntimeException("Test failed", e);
+ }
+ return addrs;
+ }
+}
--- a/jdk/test/sun/security/pkcs11/PKCS11Test.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/test/sun/security/pkcs11/PKCS11Test.java Thu Jan 14 20:57:33 2016 -0800
@@ -540,6 +540,7 @@
"/usr/lib/x86_64-linux-gnu/", "/usr/lib/x86_64-linux-gnu/nss/",
"/usr/lib64/"});
osMap.put("Linux-ppc64-64", new String[]{"/usr/lib64/"});
+ osMap.put("Linux-ppc64le-64", new String[]{"/usr/lib64/"});
osMap.put("Windows-x86-32", new String[]{
PKCS11_BASE + "/nss/lib/windows-i586/".replace('/', SEP)});
osMap.put("Windows-amd64-64", new String[]{
--- a/jdk/test/sun/tools/jinfo/JInfoRunningProcessFlagTest.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/test/sun/tools/jinfo/JInfoRunningProcessFlagTest.java Thu Jan 14 20:57:33 2016 -0800
@@ -60,30 +60,30 @@
}
private static void testFlagPlus() throws Exception {
- OutputAnalyzer output = JInfoHelper.jinfo("-flag", "+PrintGC");
+ OutputAnalyzer output = JInfoHelper.jinfo("-flag", "+HeapDumpOnOutOfMemoryError");
output.shouldHaveExitValue(0);
- output = JInfoHelper.jinfo("-flag", "PrintGC");
+ output = JInfoHelper.jinfo("-flag", "HeapDumpOnOutOfMemoryError");
output.shouldHaveExitValue(0);
- output.shouldContain("+PrintGC");
- verifyIsEnabled("PrintGC");
+ output.shouldContain("+HeapDumpOnOutOfMemoryError");
+ verifyIsEnabled("HeapDumpOnOutOfMemoryError");
}
private static void testFlagMinus() throws Exception {
- OutputAnalyzer output = JInfoHelper.jinfo("-flag", "-PrintGC");
+ OutputAnalyzer output = JInfoHelper.jinfo("-flag", "-HeapDumpOnOutOfMemoryError");
output.shouldHaveExitValue(0);
- output = JInfoHelper.jinfo("-flag", "PrintGC");
+ output = JInfoHelper.jinfo("-flag", "HeapDumpOnOutOfMemoryError");
output.shouldHaveExitValue(0);
- output.shouldContain("-PrintGC");
- verifyIsDisabled("PrintGC");
+ output.shouldContain("-HeapDumpOnOutOfMemoryError");
+ verifyIsDisabled("HeapDumpOnOutOfMemoryError");
}
private static void testFlagEqual() throws Exception {
- OutputAnalyzer output = JInfoHelper.jinfo("-flag", "PrintGC=1");
+ OutputAnalyzer output = JInfoHelper.jinfo("-flag", "HeapDumpOnOutOfMemoryError=1");
output.shouldHaveExitValue(0);
- output = JInfoHelper.jinfo("-flag", "PrintGC");
+ output = JInfoHelper.jinfo("-flag", "HeapDumpOnOutOfMemoryError");
output.shouldHaveExitValue(0);
- output.shouldContain("+PrintGC");
- verifyIsEnabled("PrintGC");
+ output.shouldContain("+HeapDumpOnOutOfMemoryError");
+ verifyIsEnabled("HeapDumpOnOutOfMemoryError");
}
private static void testInvalidFlag() throws Exception {
--- a/jdk/test/sun/tools/jps/JpsHelper.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/test/sun/tools/jps/JpsHelper.java Thu Jan 14 20:57:33 2016 -0800
@@ -98,7 +98,7 @@
* -XX:+UsePerfData is required for running the tests on embedded platforms.
*/
public static final String[] VM_ARGS = {
- "-XX:+UsePerfData", "-Xmx512m", "-XX:+PrintGCDetails",
+ "-XX:+UsePerfData", "-Xmx512m", "-Xlog:gc",
"-Dmultiline.prop=value1\nvalue2\r\nvalue3"
};
/**
--- a/jdk/test/tools/launcher/Settings.java Thu Jan 14 12:04:19 2016 -0800
+++ b/jdk/test/tools/launcher/Settings.java Thu Jan 14 20:57:33 2016 -0800
@@ -74,7 +74,7 @@
static void runTestOptionDefault() throws IOException {
String stackSize = "256"; // in kb
- if (getArch().equals("ppc64")) {
+ if (getArch().equals("ppc64") || getArch().equals("ppc64le")) {
stackSize = "800";
}
TestResult tr = null;