This commit is contained in:
Lana Steuck 2016-03-23 21:45:11 -07:00
commit 05feaeeecd
90 changed files with 5123 additions and 1648 deletions
jdk
make
src
test

@ -25,103 +25,7 @@
include Modules.gmk include Modules.gmk
BOOT_MODULES := $(eval $(call ReadImportMetaData))
UPGRADEABLE_MDOULES :=
AGGREGATOR_MDOULES :=
OTHER_PLATFORM_MODULES :=
# Hook to include the corresponding custom file, if present.
$(eval $(call IncludeCustomExtension, jdk, gensrc/GensrcModuleLoaderMap.gmk))
BOOT_MODULES += \
java.base \
java.datatransfer \
java.desktop \
java.httpclient \
java.instrument \
java.logging \
java.management \
java.naming \
java.prefs \
java.rmi \
java.security.jgss \
java.security.sasl \
java.sql \
java.xml \
java.xml.crypto \
jdk.httpserver \
jdk.management \
jdk.sctp \
jdk.security.auth \
jdk.security.jgss \
#
# to be deprivileged
BOOT_MODULES += \
java.compiler \
java.scripting \
java.sql.rowset \
java.smartcardio \
jdk.charsets \
jdk.naming.rmi \
#
UPGRADEABLE_MODULES += \
java.activation \
java.annotations.common \
java.corba \
java.transaction \
java.xml.bind \
java.xml.ws \
#
AGGREGATOR_MODULES += \
java.compact1 \
java.compact2 \
java.compact3 \
java.se \
java.se.ee \
#
OTHER_PLATFORM_MODULES += \
jdk.accessibility \
jdk.crypto.ec \
jdk.crypto.pkcs11 \
jdk.dynalink \
jdk.jsobject \
jdk.xml.dom \
jdk.localedata \
jdk.naming.dns \
jdk.scripting.nashorn \
jdk.zipfs \
#
ifeq ($(OPENJDK_TARGET_OS), macsox)
BOOT_MODULES += jdk.deploy.osx
endif
ifeq ($(OPENJDK_TARGET_OS), windows)
OTHER_PLATFORM_MODULES += jdk.crypto.mscapi
endif
ifeq ($(OPENJDK_TARGET_OS), solaris)
OTHER_PLATFORM_MODULES += jdk.crypto.ucrypto
endif
# Param 1 - Name of module
define ReadImportMetaData
ifneq ($$(wildcard $(IMPORT_MODULES_MAKE)/$$(strip $1)/build.properties), )
classloader :=
include $(IMPORT_MODULES_MAKE)/$$(strip $1)/build.properties
ifeq ($$(classloader), boot)
BOOT_MODULES += $1
else ifeq ($$(classloader), ext)
OTHER_PLATFORM_MODULES += $1
endif
endif
endef
IMPORTED_MODULES := $(call FindImportedModules)
$(foreach m, $(IMPORTED_MODULES), $(eval $(call ReadImportMetaData, $m)))
# Replacing double-comma with a single comma is to workaround the issue # Replacing double-comma with a single comma is to workaround the issue
# with some version of make on windows that doesn't substitute spaces # with some version of make on windows that doesn't substitute spaces
@ -132,7 +36,7 @@ $(strip \
) )
endef endef
BOOT_MODULES_LIST := $(call SubstComma, $(BOOT_MODULES)) BOOT_MODULES_LIST := $(call SubstComma, $(BOOT_MODULES))
PLATFORM_MODULES_LIST := $(call SubstComma, $(UPGRADEABLE_MODULES) $(AGGREGATOR_MODULES) $(OTHER_PLATFORM_MODULES)) PLATFORM_MODULES_LIST := $(call SubstComma, $(PLATFORM_MODULES))
VARDEPS_VALUE := $(BOOT_MODULES_LIST) $(PLATFORM_MODULES_LIST) VARDEPS_VALUE := $(BOOT_MODULES_LIST) $(PLATFORM_MODULES_LIST)
VARDEPS_FILE := $(call DependOnVariable, VARDEPS_VALUE) VARDEPS_FILE := $(call DependOnVariable, VARDEPS_VALUE)

@ -27,5 +27,6 @@ include LauncherCommon.gmk
$(eval $(call SetupBuildLauncher, jjs, \ $(eval $(call SetupBuildLauncher, jjs, \
MAIN_CLASS := jdk.nashorn.tools.jjs.Main, \ MAIN_CLASS := jdk.nashorn.tools.jjs.Main, \
JAVA_ARGS := -addmods ALL-SYSTEM, \
CFLAGS := -DENABLE_ARG_FILES, \ CFLAGS := -DENABLE_ARG_FILES, \
)) ))

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -36,7 +36,7 @@ import java.security.PrivilegedAction;
import java.security.PrivilegedActionException; import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import static java.io.ObjectStreamClass.processQueue; import static java.io.ObjectStreamClass.processQueue;
@ -212,20 +212,20 @@ public class ObjectInputStream
/** marker for unshared objects in internal handle table */ /** marker for unshared objects in internal handle table */
private static final Object unsharedMarker = new Object(); private static final Object unsharedMarker = new Object();
/** table mapping primitive type names to corresponding class objects */ /**
private static final HashMap<String, Class<?>> primClasses * immutable table mapping primitive type names to corresponding
= new HashMap<>(8, 1.0F); * class objects
static { */
primClasses.put("boolean", boolean.class); private static final Map<String, Class<?>> primClasses =
primClasses.put("byte", byte.class); Map.of("boolean", boolean.class,
primClasses.put("char", char.class); "byte", byte.class,
primClasses.put("short", short.class); "char", char.class,
primClasses.put("int", int.class); "short", short.class,
primClasses.put("long", long.class); "int", int.class,
primClasses.put("float", float.class); "long", long.class,
primClasses.put("double", double.class); "float", float.class,
primClasses.put("void", void.class); "double", double.class,
} "void", void.class);
private static class Caches { private static class Caches {
/** cache of subclass security audit results */ /** cache of subclass security audit results */

@ -108,11 +108,14 @@ public class MethodHandles {
* <p> * <p>
* For now, the {@linkplain Lookup#lookupClass lookup class} of this lookup * For now, the {@linkplain Lookup#lookupClass lookup class} of this lookup
* object is in an unnamed module. * object is in an unnamed module.
* Consequently, the lookup context of this lookup object will be the bootstrap
* class loader, which means it cannot find user classes.
* *
* <p style="font-size:smaller;"> * <p style="font-size:smaller;">
* <em>Discussion:</em> * <em>Discussion:</em>
* The lookup class can be changed to any other class {@code C} using an expression of the form * The lookup class can be changed to any other class {@code C} using an expression of the form
* {@link Lookup#in publicLookup().in(C.class)}. * {@link Lookup#in publicLookup().in(C.class)}.
* but may change the lookup context by virtue of changing the class loader.
* A public lookup object is always subject to * A public lookup object is always subject to
* <a href="MethodHandles.Lookup.html#secmgr">security manager checks</a>. * <a href="MethodHandles.Lookup.html#secmgr">security manager checks</a>.
* Also, it cannot access * Also, it cannot access
@ -677,6 +680,11 @@ public class MethodHandles {
* then no members, not even public members, will be accessible. * then no members, not even public members, will be accessible.
* (In all other cases, public members will continue to be accessible.) * (In all other cases, public members will continue to be accessible.)
* </ul> * </ul>
* <p>
* The resulting lookup's capabilities for loading classes
* (used during {@link #findClass} invocations)
* are determined by the lookup class' loader,
* which may change due to this operation.
* *
* @param requestedLookupClass the desired lookup class for the new lookup object * @param requestedLookupClass the desired lookup class for the new lookup object
* @return a lookup object which reports the desired lookup class * @return a lookup object which reports the desired lookup class
@ -983,13 +991,17 @@ assertEquals("[x, y, z]", pb.command().toString());
/** /**
* Looks up a class by name from the lookup context defined by this {@code Lookup} object. The static * Looks up a class by name from the lookup context defined by this {@code Lookup} object. The static
* initializer of the class is not run. * initializer of the class is not run.
* <p>
* The lookup context here is determined by the {@linkplain #lookupClass() lookup class}, its class
* loader, and the {@linkplain #lookupModes() lookup modes}. In particular, the method first attempts to
* load the requested class, and then determines whether the class is accessible to this lookup object.
* *
* @param targetName the fully qualified name of the class to be looked up. * @param targetName the fully qualified name of the class to be looked up.
* @return the requested class. * @return the requested class.
* @exception SecurityException if a security manager is present and it * @exception SecurityException if a security manager is present and it
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws LinkageError if the linkage fails * @throws LinkageError if the linkage fails
* @throws ClassNotFoundException if the class does not exist. * @throws ClassNotFoundException if the class cannot be loaded by the lookup class' loader.
* @throws IllegalAccessException if the class is not accessible, using the allowed access * @throws IllegalAccessException if the class is not accessible, using the allowed access
* modes. * modes.
* @exception SecurityException if a security manager is present and it * @exception SecurityException if a security manager is present and it
@ -1004,6 +1016,9 @@ assertEquals("[x, y, z]", pb.command().toString());
/** /**
* Determines if a class can be accessed from the lookup context defined by this {@code Lookup} object. The * Determines if a class can be accessed from the lookup context defined by this {@code Lookup} object. The
* static initializer of the class is not run. * static initializer of the class is not run.
* <p>
* The lookup context here is determined by the {@linkplain #lookupClass() lookup class} and the
* {@linkplain #lookupModes() lookup modes}.
* *
* @param targetClass the class to be access-checked * @param targetClass the class to be access-checked
* *

@ -1106,7 +1106,7 @@ public final class Instant
* complete units between the two instants. * complete units between the two instants.
* The {@code Temporal} passed to this method is converted to a * The {@code Temporal} passed to this method is converted to a
* {@code Instant} using {@link #from(TemporalAccessor)}. * {@code Instant} using {@link #from(TemporalAccessor)}.
* For example, the amount in days between two dates can be calculated * For example, the amount in seconds between two dates can be calculated
* using {@code startInstant.until(endInstant, SECONDS)}. * using {@code startInstant.until(endInstant, SECONDS)}.
* <p> * <p>
* There are two equivalent ways of using this method. * There are two equivalent ways of using this method.

@ -619,6 +619,9 @@ public final class DateTimeFormatter {
* The returned formatter has a chronology of ISO set to ensure dates in * The returned formatter has a chronology of ISO set to ensure dates in
* other calendar systems are correctly converted. * other calendar systems are correctly converted.
* It has no override zone and uses the {@link ResolverStyle#SMART SMART} resolver style. * It has no override zone and uses the {@link ResolverStyle#SMART SMART} resolver style.
* The {@code FULL} and {@code LONG} styles typically require a time-zone.
* When formatting using these styles, a {@code ZoneId} must be available,
* either by using {@code ZonedDateTime} or {@link DateTimeFormatter#withZone}.
* *
* @param timeStyle the formatter style to obtain, not null * @param timeStyle the formatter style to obtain, not null
* @return the time formatter, not null * @return the time formatter, not null
@ -647,6 +650,9 @@ public final class DateTimeFormatter {
* The returned formatter has a chronology of ISO set to ensure dates in * The returned formatter has a chronology of ISO set to ensure dates in
* other calendar systems are correctly converted. * other calendar systems are correctly converted.
* It has no override zone and uses the {@link ResolverStyle#SMART SMART} resolver style. * It has no override zone and uses the {@link ResolverStyle#SMART SMART} resolver style.
* The {@code FULL} and {@code LONG} styles typically require a time-zone.
* When formatting using these styles, a {@code ZoneId} must be available,
* either by using {@code ZonedDateTime} or {@link DateTimeFormatter#withZone}.
* *
* @param dateTimeStyle the formatter style to obtain, not null * @param dateTimeStyle the formatter style to obtain, not null
* @return the date-time formatter, not null * @return the date-time formatter, not null
@ -675,6 +681,9 @@ public final class DateTimeFormatter {
* The returned formatter has a chronology of ISO set to ensure dates in * The returned formatter has a chronology of ISO set to ensure dates in
* other calendar systems are correctly converted. * other calendar systems are correctly converted.
* It has no override zone and uses the {@link ResolverStyle#SMART SMART} resolver style. * It has no override zone and uses the {@link ResolverStyle#SMART SMART} resolver style.
* The {@code FULL} and {@code LONG} styles typically require a time-zone.
* When formatting using these styles, a {@code ZoneId} must be available,
* either by using {@code ZonedDateTime} or {@link DateTimeFormatter#withZone}.
* *
* @param dateStyle the date formatter style to obtain, not null * @param dateStyle the date formatter style to obtain, not null
* @param timeStyle the time formatter style to obtain, not null * @param timeStyle the time formatter style to obtain, not null
@ -923,6 +932,7 @@ public final class DateTimeFormatter {
* <li>The {@link #ISO_LOCAL_DATE_TIME} * <li>The {@link #ISO_LOCAL_DATE_TIME}
* <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then * <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
* they will be handled even though this is not part of the ISO-8601 standard. * they will be handled even though this is not part of the ISO-8601 standard.
* The offset parsing is lenient, which allows the minutes and seconds to be optional.
* Parsing is case insensitive. * Parsing is case insensitive.
* </ul> * </ul>
* <p> * <p>
@ -935,7 +945,9 @@ public final class DateTimeFormatter {
ISO_OFFSET_DATE_TIME = new DateTimeFormatterBuilder() ISO_OFFSET_DATE_TIME = new DateTimeFormatterBuilder()
.parseCaseInsensitive() .parseCaseInsensitive()
.append(ISO_LOCAL_DATE_TIME) .append(ISO_LOCAL_DATE_TIME)
.parseLenient()
.appendOffsetId() .appendOffsetId()
.parseStrict()
.toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE); .toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
} }
@ -1160,6 +1172,7 @@ public final class DateTimeFormatter {
* <li>If the offset is not available to format or parse then the format is complete. * <li>If the offset is not available to format or parse then the format is complete.
* <li>The {@link ZoneOffset#getId() offset ID} without colons. If the offset has * <li>The {@link ZoneOffset#getId() offset ID} without colons. If the offset has
* seconds then they will be handled even though this is not part of the ISO-8601 standard. * seconds then they will be handled even though this is not part of the ISO-8601 standard.
* The offset parsing is lenient, which allows the minutes and seconds to be optional.
* Parsing is case insensitive. * Parsing is case insensitive.
* </ul> * </ul>
* <p> * <p>
@ -1178,7 +1191,9 @@ public final class DateTimeFormatter {
.appendValue(MONTH_OF_YEAR, 2) .appendValue(MONTH_OF_YEAR, 2)
.appendValue(DAY_OF_MONTH, 2) .appendValue(DAY_OF_MONTH, 2)
.optionalStart() .optionalStart()
.parseLenient()
.appendOffset("+HHMMss", "Z") .appendOffset("+HHMMss", "Z")
.parseStrict()
.toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE); .toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
} }

@ -866,7 +866,9 @@ public final class DateTimeFormatterBuilder {
* Appends the zone offset, such as '+01:00', to the formatter. * Appends the zone offset, such as '+01:00', to the formatter.
* <p> * <p>
* This appends an instruction to format/parse the offset ID to the builder. * This appends an instruction to format/parse the offset ID to the builder.
* This is equivalent to calling {@code appendOffset("+HH:MM:ss", "Z")}. * This is equivalent to calling {@code appendOffset("+HH:mm:ss", "Z")}.
* See {@link #appendOffset(String, String)} for details on formatting
* and parsing.
* *
* @return this, for chaining, not null * @return this, for chaining, not null
*/ */
@ -886,9 +888,18 @@ public final class DateTimeFormatterBuilder {
* If the offset cannot be obtained then an exception is thrown unless the * If the offset cannot be obtained then an exception is thrown unless the
* section of the formatter is optional. * section of the formatter is optional.
* <p> * <p>
* During parsing, the offset is parsed using the format defined below. * When parsing in strict mode, the input must contain the mandatory
* If the offset cannot be parsed then an exception is thrown unless the * and optional elements are defined by the specified pattern.
* section of the formatter is optional. * If the offset cannot be parsed then an exception is thrown unless
* the section of the formatter is optional.
* <p>
* When parsing in lenient mode, only the hours are mandatory - minutes
* and seconds are optional. The colons are required if the specified
* pattern contains a colon. If the specified pattern is "+HH", the
* presence of colons is determined by whether the character after the
* hour digits is a colon or not.
* If the offset cannot be parsed then an exception is thrown unless
* the section of the formatter is optional.
* <p> * <p>
* The format of the offset is controlled by a pattern which must be one * The format of the offset is controlled by a pattern which must be one
* of the following: * of the following:
@ -902,6 +913,10 @@ public final class DateTimeFormatterBuilder {
* <li>{@code +HH:MM:ss} - hour and minute, with second if non-zero, with colon * <li>{@code +HH:MM:ss} - hour and minute, with second if non-zero, with colon
* <li>{@code +HHMMSS} - hour, minute and second, no colon * <li>{@code +HHMMSS} - hour, minute and second, no colon
* <li>{@code +HH:MM:SS} - hour, minute and second, with colon * <li>{@code +HH:MM:SS} - hour, minute and second, with colon
* <li>{@code +HHmmss} - hour, with minute if non-zero or with minute and
* second if non-zero, no colon
* <li>{@code +HH:mm:ss} - hour, with minute if non-zero or with minute and
* second if non-zero, with colon
* </ul> * </ul>
* The "no offset" text controls what text is printed when the total amount of * The "no offset" text controls what text is printed when the total amount of
* the offset fields to be output is zero. * the offset fields to be output is zero.
@ -1256,6 +1271,9 @@ public final class DateTimeFormatterBuilder {
* During formatting, the chronology is obtained from the temporal object * During formatting, the chronology is obtained from the temporal object
* being formatted, which may have been overridden by * being formatted, which may have been overridden by
* {@link DateTimeFormatter#withChronology(Chronology)}. * {@link DateTimeFormatter#withChronology(Chronology)}.
* The {@code FULL} and {@code LONG} styles typically require a time-zone.
* When formatting using these styles, a {@code ZoneId} must be available,
* either by using {@code ZonedDateTime} or {@link DateTimeFormatter#withZone}.
* <p> * <p>
* During parsing, if a chronology has already been parsed, then it is used. * During parsing, if a chronology has already been parsed, then it is used.
* Otherwise the default from {@code DateTimeFormatter.withChronology(Chronology)} * Otherwise the default from {@code DateTimeFormatter.withChronology(Chronology)}
@ -3315,7 +3333,7 @@ public final class DateTimeFormatterBuilder {
*/ */
static final class OffsetIdPrinterParser implements DateTimePrinterParser { static final class OffsetIdPrinterParser implements DateTimePrinterParser {
static final String[] PATTERNS = new String[] { static final String[] PATTERNS = new String[] {
"+HH", "+HHmm", "+HH:mm", "+HHMM", "+HH:MM", "+HHMMss", "+HH:MM:ss", "+HHMMSS", "+HH:MM:SS", "+HH", "+HHmm", "+HH:mm", "+HHMM", "+HH:MM", "+HHMMss", "+HH:MM:ss", "+HHMMSS", "+HH:MM:SS", "+HHmmss", "+HH:mm:ss",
}; // order used in pattern builder }; // order used in pattern builder
static final OffsetIdPrinterParser INSTANCE_ID_Z = new OffsetIdPrinterParser("+HH:MM:ss", "Z"); static final OffsetIdPrinterParser INSTANCE_ID_Z = new OffsetIdPrinterParser("+HH:MM:ss", "Z");
static final OffsetIdPrinterParser INSTANCE_ID_ZERO = new OffsetIdPrinterParser("+HH:MM:ss", "0"); static final OffsetIdPrinterParser INSTANCE_ID_ZERO = new OffsetIdPrinterParser("+HH:MM:ss", "0");
@ -3362,11 +3380,11 @@ public final class DateTimeFormatterBuilder {
int output = absHours; int output = absHours;
buf.append(totalSecs < 0 ? "-" : "+") buf.append(totalSecs < 0 ? "-" : "+")
.append((char) (absHours / 10 + '0')).append((char) (absHours % 10 + '0')); .append((char) (absHours / 10 + '0')).append((char) (absHours % 10 + '0'));
if (type >= 3 || (type >= 1 && absMinutes > 0)) { if ((type >= 3 && type < 9) || (type >= 9 && absSeconds > 0) || (type >= 1 && absMinutes > 0)) {
buf.append((type % 2) == 0 ? ":" : "") buf.append((type % 2) == 0 ? ":" : "")
.append((char) (absMinutes / 10 + '0')).append((char) (absMinutes % 10 + '0')); .append((char) (absMinutes / 10 + '0')).append((char) (absMinutes % 10 + '0'));
output += absMinutes; output += absMinutes;
if (type >= 7 || (type >= 5 && absSeconds > 0)) { if (type == 7 || type == 8 || (type >= 5 && absSeconds > 0)) {
buf.append((type % 2) == 0 ? ":" : "") buf.append((type % 2) == 0 ? ":" : "")
.append((char) (absSeconds / 10 + '0')).append((char) (absSeconds % 10 + '0')); .append((char) (absSeconds / 10 + '0')).append((char) (absSeconds % 10 + '0'));
output += absSeconds; output += absSeconds;
@ -3384,6 +3402,15 @@ public final class DateTimeFormatterBuilder {
public int parse(DateTimeParseContext context, CharSequence text, int position) { public int parse(DateTimeParseContext context, CharSequence text, int position) {
int length = text.length(); int length = text.length();
int noOffsetLen = noOffsetText.length(); int noOffsetLen = noOffsetText.length();
int parseType = type;
if (context.isStrict() == false) {
if ((parseType > 0 && (parseType % 2) == 0) ||
(parseType == 0 && length > position + 3 && text.charAt(position + 3) == ':')) {
parseType = 10;
} else {
parseType = 9;
}
}
if (noOffsetLen == 0) { if (noOffsetLen == 0) {
if (position == length) { if (position == length) {
return context.setParsedField(OFFSET_SECONDS, 0, position, position); return context.setParsedField(OFFSET_SECONDS, 0, position, position);
@ -3404,9 +3431,9 @@ public final class DateTimeFormatterBuilder {
int negative = (sign == '-' ? -1 : 1); int negative = (sign == '-' ? -1 : 1);
int[] array = new int[4]; int[] array = new int[4];
array[0] = position + 1; array[0] = position + 1;
if ((parseNumber(array, 1, text, true) || if ((parseNumber(array, 1, text, true, parseType) ||
parseNumber(array, 2, text, type >=3) || parseNumber(array, 2, text, parseType >= 3 && parseType < 9, parseType) ||
parseNumber(array, 3, text, false)) == false) { parseNumber(array, 3, text, parseType == 7 || parseType == 8, parseType)) == false) {
// success // success
long offsetSecs = negative * (array[1] * 3600L + array[2] * 60L + array[3]); long offsetSecs = negative * (array[1] * 3600L + array[2] * 60L + array[3]);
return context.setParsedField(OFFSET_SECONDS, offsetSecs, position, array[0]); return context.setParsedField(OFFSET_SECONDS, offsetSecs, position, array[0]);
@ -3414,7 +3441,7 @@ public final class DateTimeFormatterBuilder {
} }
// handle special case of empty no offset text // handle special case of empty no offset text
if (noOffsetLen == 0) { if (noOffsetLen == 0) {
return context.setParsedField(OFFSET_SECONDS, 0, position, position + noOffsetLen); return context.setParsedField(OFFSET_SECONDS, 0, position, position);
} }
return ~position; return ~position;
} }
@ -3426,14 +3453,15 @@ public final class DateTimeFormatterBuilder {
* @param arrayIndex the index to parse the value into * @param arrayIndex the index to parse the value into
* @param parseText the offset ID, not null * @param parseText the offset ID, not null
* @param required whether this number is required * @param required whether this number is required
* @param parseType the offset pattern type
* @return true if an error occurred * @return true if an error occurred
*/ */
private boolean parseNumber(int[] array, int arrayIndex, CharSequence parseText, boolean required) { private boolean parseNumber(int[] array, int arrayIndex, CharSequence parseText, boolean required, int parseType) {
if ((type + 3) / 2 < arrayIndex) { if ((parseType + 3) / 2 < arrayIndex) {
return false; // ignore seconds/minutes return false; // ignore seconds/minutes
} }
int pos = array[0]; int pos = array[0];
if ((type % 2) == 0 && arrayIndex > 1) { if ((parseType % 2) == 0 && arrayIndex > 1) {
if (pos + 1 > parseText.length() || parseText.charAt(pos) != ':') { if (pos + 1 > parseText.length() || parseText.charAt(pos) != ':') {
return required; return required;
} }

@ -218,6 +218,13 @@ final class DateTimePrintContext {
} }
return query.queryFrom(this); return query.queryFrom(this);
} }
@Override
public String toString() {
return temporal +
(effectiveChrono != null ? " with chronology " + effectiveChrono : "") +
(effectiveZone != null ? " with zone " + effectiveZone : "");
}
}; };
} }
@ -279,7 +286,8 @@ final class DateTimePrintContext {
<R> R getValue(TemporalQuery<R> query) { <R> R getValue(TemporalQuery<R> query) {
R result = temporal.query(query); R result = temporal.query(query);
if (result == null && optional == 0) { if (result == null && optional == 0) {
throw new DateTimeException("Unable to extract value: " + temporal.getClass()); throw new DateTimeException("Unable to extract " +
query + " from temporal " + temporal);
} }
return result; return result;
} }

@ -341,58 +341,118 @@ public final class TemporalQueries {
/** /**
* A strict query for the {@code ZoneId}. * A strict query for the {@code ZoneId}.
*/ */
static final TemporalQuery<ZoneId> ZONE_ID = (temporal) -> static final TemporalQuery<ZoneId> ZONE_ID = new TemporalQuery<>() {
temporal.query(TemporalQueries.ZONE_ID); @Override
public ZoneId queryFrom(TemporalAccessor temporal) {
return temporal.query(TemporalQueries.ZONE_ID);
}
@Override
public String toString() {
return "ZoneId";
}
};
/** /**
* A query for the {@code Chronology}. * A query for the {@code Chronology}.
*/ */
static final TemporalQuery<Chronology> CHRONO = (temporal) -> static final TemporalQuery<Chronology> CHRONO = new TemporalQuery<>() {
temporal.query(TemporalQueries.CHRONO); @Override
public Chronology queryFrom(TemporalAccessor temporal) {
return temporal.query(TemporalQueries.CHRONO);
}
@Override
public String toString() {
return "Chronology";
}
};
/** /**
* A query for the smallest supported unit. * A query for the smallest supported unit.
*/ */
static final TemporalQuery<TemporalUnit> PRECISION = (temporal) -> static final TemporalQuery<TemporalUnit> PRECISION = new TemporalQuery<>() {
temporal.query(TemporalQueries.PRECISION); @Override
public TemporalUnit queryFrom(TemporalAccessor temporal) {
return temporal.query(TemporalQueries.PRECISION);
}
@Override
public String toString() {
return "Precision";
}
};
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
/** /**
* A query for {@code ZoneOffset} returning null if not found. * A query for {@code ZoneOffset} returning null if not found.
*/ */
static final TemporalQuery<ZoneOffset> OFFSET = (temporal) -> { static final TemporalQuery<ZoneOffset> OFFSET = new TemporalQuery<>() {
if (temporal.isSupported(OFFSET_SECONDS)) { @Override
return ZoneOffset.ofTotalSeconds(temporal.get(OFFSET_SECONDS)); public ZoneOffset queryFrom(TemporalAccessor temporal) {
if (temporal.isSupported(OFFSET_SECONDS)) {
return ZoneOffset.ofTotalSeconds(temporal.get(OFFSET_SECONDS));
}
return null;
}
@Override
public String toString() {
return "ZoneOffset";
} }
return null;
}; };
/** /**
* A lenient query for the {@code ZoneId}, falling back to the {@code ZoneOffset}. * A lenient query for the {@code ZoneId}, falling back to the {@code ZoneOffset}.
*/ */
static final TemporalQuery<ZoneId> ZONE = (temporal) -> { static final TemporalQuery<ZoneId> ZONE = new TemporalQuery<>() {
ZoneId zone = temporal.query(ZONE_ID); @Override
return (zone != null ? zone : temporal.query(OFFSET)); public ZoneId queryFrom(TemporalAccessor temporal) {
ZoneId zone = temporal.query(ZONE_ID);
return (zone != null ? zone : temporal.query(OFFSET));
}
@Override
public String toString() {
return "Zone";
}
}; };
/** /**
* A query for {@code LocalDate} returning null if not found. * A query for {@code LocalDate} returning null if not found.
*/ */
static final TemporalQuery<LocalDate> LOCAL_DATE = (temporal) -> { static final TemporalQuery<LocalDate> LOCAL_DATE = new TemporalQuery<>() {
if (temporal.isSupported(EPOCH_DAY)) { @Override
return LocalDate.ofEpochDay(temporal.getLong(EPOCH_DAY)); public LocalDate queryFrom(TemporalAccessor temporal) {
if (temporal.isSupported(EPOCH_DAY)) {
return LocalDate.ofEpochDay(temporal.getLong(EPOCH_DAY));
}
return null;
}
@Override
public String toString() {
return "LocalDate";
} }
return null;
}; };
/** /**
* A query for {@code LocalTime} returning null if not found. * A query for {@code LocalTime} returning null if not found.
*/ */
static final TemporalQuery<LocalTime> LOCAL_TIME = (temporal) -> { static final TemporalQuery<LocalTime> LOCAL_TIME = new TemporalQuery<>() {
if (temporal.isSupported(NANO_OF_DAY)) { @Override
return LocalTime.ofNanoOfDay(temporal.getLong(NANO_OF_DAY)); public LocalTime queryFrom(TemporalAccessor temporal) {
if (temporal.isSupported(NANO_OF_DAY)) {
return LocalTime.ofNanoOfDay(temporal.getLong(NANO_OF_DAY));
}
return null;
}
@Override
public String toString() {
return "LocalTime";
} }
return null;
}; };
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -1281,8 +1281,74 @@ public class ArrayList<E> extends AbstractList<E>
public Spliterator<E> spliterator() { public Spliterator<E> spliterator() {
checkForComodification(); checkForComodification();
return new ArrayListSpliterator<>(ArrayList.this, offset,
offset + this.size, this.modCount); return new Spliterator<>() {
private int index = offset; // current index, modified on advance/split
private int fence = -1; // -1 until used; then one past last index
private int expectedModCount; // initialized when fence set
private int getFence() { // initialize fence to size on first use
int hi; // (a specialized variant appears in method forEach)
if ((hi = fence) < 0) {
expectedModCount = modCount;
hi = fence = offset + size;
}
return hi;
}
public ArrayListSpliterator<E> trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid) ? null : // divide range in half unless too small
new ArrayListSpliterator<>(ArrayList.this, lo, index = mid,
expectedModCount);
}
public boolean tryAdvance(Consumer<? super E> action) {
Objects.requireNonNull(action);
int hi = getFence(), i = index;
if (i < hi) {
index = i + 1;
@SuppressWarnings("unchecked") E e = (E)elementData[i];
action.accept(e);
if (ArrayList.this.modCount != expectedModCount)
throw new ConcurrentModificationException();
return true;
}
return false;
}
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
int i, hi, mc; // hoist accesses and checks from loop
ArrayList<E> lst = ArrayList.this;
Object[] a;
if ((a = lst.elementData) != null) {
if ((hi = fence) < 0) {
mc = modCount;
hi = offset + size;
}
else
mc = expectedModCount;
if ((i = index) >= 0 && (index = hi) <= a.length) {
for (; i < hi; ++i) {
@SuppressWarnings("unchecked") E e = (E) a[i];
action.accept(e);
}
if (lst.modCount == mc)
return;
}
}
throw new ConcurrentModificationException();
}
public long estimateSize() {
return (long) (getFence() - index);
}
public int characteristics() {
return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
}
};
} }
} }

@ -718,7 +718,7 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
} }
/** /**
* Returns a shallow copy of this enum map. (The values themselves * Returns a shallow copy of this enum map. The values themselves
* are not cloned. * are not cloned.
* *
* @return a shallow copy of this enum map * @return a shallow copy of this enum map

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -656,8 +656,9 @@ public final class Collectors {
*/ */
return new CollectorImpl<>( return new CollectorImpl<>(
() -> new double[3], () -> new double[3],
(a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t)); (a, t) -> { double val = mapper.applyAsDouble(t);
a[2] += mapper.applyAsDouble(t);}, sumWithCompensation(a, val);
a[2] += val;},
(a, b) -> { sumWithCompensation(a, b[0]); (a, b) -> { sumWithCompensation(a, b[0]);
a[2] += b[2]; a[2] += b[2];
return sumWithCompensation(a, b[1]); }, return sumWithCompensation(a, b[1]); },
@ -768,7 +769,7 @@ public final class Collectors {
*/ */
return new CollectorImpl<>( return new CollectorImpl<>(
() -> new double[4], () -> new double[4],
(a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t)); a[2]++; a[3]+= mapper.applyAsDouble(t);}, (a, t) -> { double val = mapper.applyAsDouble(t); sumWithCompensation(a, val); a[2]++; a[3]+= val;},
(a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, b[1]); a[2] += b[2]; a[3] += b[3]; return a; }, (a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, b[1]); a[2] += b[2]; a[3] += b[3]; return a; },
a -> (a[2] == 0) ? 0.0d : (computeFinalSum(a) / a[2]), a -> (a[2] == 0) ? 0.0d : (computeFinalSum(a) / a[2]),
CH_NOID); CH_NOID);

@ -98,7 +98,7 @@ abstract class PipelineHelper<P_OUT> {
* @implSpec * @implSpec
* The implementation behaves as if: * The implementation behaves as if:
* <pre>{@code * <pre>{@code
* intoWrapped(wrapSink(sink), spliterator); * copyInto(wrapSink(sink), spliterator);
* }</pre> * }</pre>
* *
* @param sink the {@code Sink} to receive the results * @param sink the {@code Sink} to receive the results

@ -40,6 +40,15 @@ import jdk.internal.HotSpotIntrinsicCandidate;
* Although the class and all methods are public, use of this class is * Although the class and all methods are public, use of this class is
* limited because only trusted code can obtain instances of it. * limited because only trusted code can obtain instances of it.
* *
* <em>Note:</em> It is the resposibility of the caller to make sure
* arguments are checked before methods of this class are
* called. While some rudimentary checks are performed on the input,
* the checks are best effort and when performance is an overriding
* priority, as when methods of this class are optimized by the
* runtime compiler, some or all checks (if any) may be elided. Hence,
* the caller must not rely on the checks and corresponding
* exceptions!
*
* @author John R. Rose * @author John R. Rose
* @see #getUnsafe * @see #getUnsafe
*/ */
@ -358,6 +367,169 @@ public final class Unsafe {
@HotSpotIntrinsicCandidate @HotSpotIntrinsicCandidate
public native void putAddress(long address, long x); public native void putAddress(long address, long x);
/// helper methods for validating various types of objects/values
/**
* Create an exception reflecting that some of the input was invalid
*
* <em>Note:</em> It is the resposibility of the caller to make
* sure arguments are checked before the methods are called. While
* some rudimentary checks are performed on the input, the checks
* are best effort and when performance is an overriding priority,
* as when methods of this class are optimized by the runtime
* compiler, some or all checks (if any) may be elided. Hence, the
* caller must not rely on the checks and corresponding
* exceptions!
*
* @return an exception object
*/
private RuntimeException invalidInput() {
return new IllegalArgumentException();
}
/**
* Check if a value is 32-bit clean (32 MSB are all zero)
*
* @param value the 64-bit value to check
*
* @return true if the value is 32-bit clean
*/
private boolean is32BitClean(long value) {
return value >>> 32 == 0;
}
/**
* Check the validity of a size (the equivalent of a size_t)
*
* @throws RuntimeException if the size is invalid
* (<em>Note:</em> after optimization, invalid inputs may
* go undetected, which will lead to unpredictable
* behavior)
*/
private void checkSize(long size) {
if (ADDRESS_SIZE == 4) {
// Note: this will also check for negative sizes
if (!is32BitClean(size)) {
throw invalidInput();
}
} else if (size < 0) {
throw invalidInput();
}
}
/**
* Check the validity of a native address (the equivalent of void*)
*
* @throws RuntimeException if the address is invalid
* (<em>Note:</em> after optimization, invalid inputs may
* go undetected, which will lead to unpredictable
* behavior)
*/
private void checkNativeAddress(long address) {
if (ADDRESS_SIZE == 4) {
// Accept both zero and sign extended pointers. A valid
// pointer will, after the +1 below, either have produced
// the value 0x0 or 0x1. Masking off the low bit allows
// for testing against 0.
if ((((address >> 32) + 1) & ~1) != 0) {
throw invalidInput();
}
}
}
/**
* Check the validity of an offset, relative to a base object
*
* @param o the base object
* @param offset the offset to check
*
* @throws RuntimeException if the size is invalid
* (<em>Note:</em> after optimization, invalid inputs may
* go undetected, which will lead to unpredictable
* behavior)
*/
private void checkOffset(Object o, long offset) {
if (ADDRESS_SIZE == 4) {
// Note: this will also check for negative offsets
if (!is32BitClean(offset)) {
throw invalidInput();
}
} else if (offset < 0) {
throw invalidInput();
}
}
/**
* Check the validity of a double-register pointer
*
* Note: This code deliberately does *not* check for NPE for (at
* least) three reasons:
*
* 1) NPE is not just NULL/0 - there is a range of values all
* resulting in an NPE, which is not trivial to check for
*
* 2) It is the responsibility of the callers of Unsafe methods
* to verify the input, so throwing an exception here is not really
* useful - passing in a NULL pointer is a critical error and the
* must not expect an exception to be thrown anyway.
*
* 3) the actual operations will detect NULL pointers anyway by
* means of traps and signals (like SIGSEGV).
*
* @param o Java heap object, or null
* @param offset indication of where the variable resides in a Java heap
* object, if any, else a memory address locating the variable
* statically
*
* @throws RuntimeException if the pointer is invalid
* (<em>Note:</em> after optimization, invalid inputs may
* go undetected, which will lead to unpredictable
* behavior)
*/
private void checkPointer(Object o, long offset) {
if (o == null) {
checkNativeAddress(offset);
} else {
checkOffset(o, offset);
}
}
/**
* Check if a type is a primitive array type
*
* @param c the type to check
*
* @return true if the type is a primitive array type
*/
private void checkPrimitiveArray(Class<?> c) {
Class<?> componentType = c.getComponentType();
if (componentType == null || !componentType.isPrimitive()) {
throw invalidInput();
}
}
/**
* Check that a pointer is a valid primitive array type pointer
*
* Note: pointers off-heap are considered to be primitive arrays
*
* @throws RuntimeException if the pointer is invalid
* (<em>Note:</em> after optimization, invalid inputs may
* go undetected, which will lead to unpredictable
* behavior)
*/
private void checkPrimitivePointer(Object o, long offset) {
checkPointer(o, offset);
if (o != null) {
// If on heap, it it must be a primitive array
checkPrimitiveArray(o.getClass());
}
}
/// wrappers for malloc, realloc, free: /// wrappers for malloc, realloc, free:
/** /**
@ -367,7 +539,16 @@ public final class Unsafe {
* aligned for all value types. Dispose of this memory by calling {@link * aligned for all value types. Dispose of this memory by calling {@link
* #freeMemory}, or resize it with {@link #reallocateMemory}. * #freeMemory}, or resize it with {@link #reallocateMemory}.
* *
* @throws IllegalArgumentException if the size is negative or too large * <em>Note:</em> It is the resposibility of the caller to make
* sure arguments are checked before the methods are called. While
* some rudimentary checks are performed on the input, the checks
* are best effort and when performance is an overriding priority,
* as when methods of this class are optimized by the runtime
* compiler, some or all checks (if any) may be elided. Hence, the
* caller must not rely on the checks and corresponding
* exceptions!
*
* @throws RuntimeException if the size is negative or too large
* for the native size_t type * for the native size_t type
* *
* @throws OutOfMemoryError if the allocation is refused by the system * @throws OutOfMemoryError if the allocation is refused by the system
@ -375,7 +556,32 @@ public final class Unsafe {
* @see #getByte(long) * @see #getByte(long)
* @see #putByte(long, byte) * @see #putByte(long, byte)
*/ */
public native long allocateMemory(long bytes); public long allocateMemory(long bytes) {
allocateMemoryChecks(bytes);
if (bytes == 0) {
return 0;
}
long p = allocateMemory0(bytes);
if (p == 0) {
throw new OutOfMemoryError();
}
return p;
}
/**
* Validate the arguments to allocateMemory
*
* @throws RuntimeException if the arguments are invalid
* (<em>Note:</em> after optimization, invalid inputs may
* go undetected, which will lead to unpredictable
* behavior)
*/
private void allocateMemoryChecks(long bytes) {
checkSize(bytes);
}
/** /**
* Resizes a new block of native memory, to the given size in bytes. The * Resizes a new block of native memory, to the given size in bytes. The
@ -387,14 +593,50 @@ public final class Unsafe {
* #reallocateMemory}. The address passed to this method may be null, in * #reallocateMemory}. The address passed to this method may be null, in
* which case an allocation will be performed. * which case an allocation will be performed.
* *
* @throws IllegalArgumentException if the size is negative or too large * <em>Note:</em> It is the resposibility of the caller to make
* sure arguments are checked before the methods are called. While
* some rudimentary checks are performed on the input, the checks
* are best effort and when performance is an overriding priority,
* as when methods of this class are optimized by the runtime
* compiler, some or all checks (if any) may be elided. Hence, the
* caller must not rely on the checks and corresponding
* exceptions!
*
* @throws RuntimeException if the size is negative or too large
* for the native size_t type * for the native size_t type
* *
* @throws OutOfMemoryError if the allocation is refused by the system * @throws OutOfMemoryError if the allocation is refused by the system
* *
* @see #allocateMemory * @see #allocateMemory
*/ */
public native long reallocateMemory(long address, long bytes); public long reallocateMemory(long address, long bytes) {
reallocateMemoryChecks(address, bytes);
if (bytes == 0) {
freeMemory(address);
return 0;
}
long p = (address == 0) ? allocateMemory0(bytes) : reallocateMemory0(address, bytes);
if (p == 0) {
throw new OutOfMemoryError();
}
return p;
}
/**
* Validate the arguments to reallocateMemory
*
* @throws RuntimeException if the arguments are invalid
* (<em>Note:</em> after optimization, invalid inputs may
* go undetected, which will lead to unpredictable
* behavior)
*/
private void reallocateMemoryChecks(long address, long bytes) {
checkPointer(null, address);
checkSize(bytes);
}
/** /**
* Sets all bytes in a given block of memory to a fixed value * Sets all bytes in a given block of memory to a fixed value
@ -411,9 +653,28 @@ public final class Unsafe {
* If the effective address and length are (resp.) even modulo 4 or 2, * If the effective address and length are (resp.) even modulo 4 or 2,
* the stores take place in units of 'int' or 'short'. * the stores take place in units of 'int' or 'short'.
* *
* <em>Note:</em> It is the resposibility of the caller to make
* sure arguments are checked before the methods are called. While
* some rudimentary checks are performed on the input, the checks
* are best effort and when performance is an overriding priority,
* as when methods of this class are optimized by the runtime
* compiler, some or all checks (if any) may be elided. Hence, the
* caller must not rely on the checks and corresponding
* exceptions!
*
* @throws RuntimeException if any of the arguments is invalid
*
* @since 1.7 * @since 1.7
*/ */
public native void setMemory(Object o, long offset, long bytes, byte value); public void setMemory(Object o, long offset, long bytes, byte value) {
setMemoryChecks(o, offset, bytes, value);
if (bytes == 0) {
return;
}
setMemory0(o, offset, bytes, value);
}
/** /**
* Sets all bytes in a given block of memory to a fixed value * Sets all bytes in a given block of memory to a fixed value
@ -426,6 +687,19 @@ public final class Unsafe {
setMemory(null, address, bytes, value); setMemory(null, address, bytes, value);
} }
/**
* Validate the arguments to setMemory
*
* @throws RuntimeException if the arguments are invalid
* (<em>Note:</em> after optimization, invalid inputs may
* go undetected, which will lead to unpredictable
* behavior)
*/
private void setMemoryChecks(Object o, long offset, long bytes, byte value) {
checkPrimitivePointer(o, offset);
checkSize(bytes);
}
/** /**
* Sets all bytes in a given block of memory to a copy of another * Sets all bytes in a given block of memory to a copy of another
* block. * block.
@ -441,12 +715,31 @@ public final class Unsafe {
* If the effective addresses and length are (resp.) even modulo 4 or 2, * If the effective addresses and length are (resp.) even modulo 4 or 2,
* the transfer takes place in units of 'int' or 'short'. * the transfer takes place in units of 'int' or 'short'.
* *
* <em>Note:</em> It is the resposibility of the caller to make
* sure arguments are checked before the methods are called. While
* some rudimentary checks are performed on the input, the checks
* are best effort and when performance is an overriding priority,
* as when methods of this class are optimized by the runtime
* compiler, some or all checks (if any) may be elided. Hence, the
* caller must not rely on the checks and corresponding
* exceptions!
*
* @throws RuntimeException if any of the arguments is invalid
*
* @since 1.7 * @since 1.7
*/ */
@HotSpotIntrinsicCandidate public void copyMemory(Object srcBase, long srcOffset,
public native void copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset,
Object destBase, long destOffset, long bytes) {
long bytes); copyMemoryChecks(srcBase, srcOffset, destBase, destOffset, bytes);
if (bytes == 0) {
return;
}
copyMemory0(srcBase, srcOffset, destBase, destOffset, bytes);
}
/** /**
* Sets all bytes in a given block of memory to a copy of another * Sets all bytes in a given block of memory to a copy of another
* block. This provides a <em>single-register</em> addressing mode, * block. This provides a <em>single-register</em> addressing mode,
@ -458,15 +751,22 @@ public final class Unsafe {
copyMemory(null, srcAddress, null, destAddress, bytes); copyMemory(null, srcAddress, null, destAddress, bytes);
} }
private boolean isPrimitiveArray(Class<?> c) { /**
Class<?> componentType = c.getComponentType(); * Validate the arguments to copyMemory
return componentType != null && componentType.isPrimitive(); *
* @throws RuntimeException if any of the arguments is invalid
* (<em>Note:</em> after optimization, invalid inputs may
* go undetected, which will lead to unpredictable
* behavior)
*/
private void copyMemoryChecks(Object srcBase, long srcOffset,
Object destBase, long destOffset,
long bytes) {
checkSize(bytes);
checkPrimitivePointer(srcBase, srcOffset);
checkPrimitivePointer(destBase, destOffset);
} }
private native void copySwapMemory0(Object srcBase, long srcOffset,
Object destBase, long destOffset,
long bytes, long elemSize);
/** /**
* Copies all elements from one block of memory to another block, * Copies all elements from one block of memory to another block,
* *unconditionally* byte swapping the elements on the fly. * *unconditionally* byte swapping the elements on the fly.
@ -476,39 +776,23 @@ public final class Unsafe {
* as discussed in {@link #getInt(Object,long)}. When the object reference is null, * as discussed in {@link #getInt(Object,long)}. When the object reference is null,
* the offset supplies an absolute base address. * the offset supplies an absolute base address.
* *
* <em>Note:</em> It is the resposibility of the caller to make
* sure arguments are checked before the methods are called. While
* some rudimentary checks are performed on the input, the checks
* are best effort and when performance is an overriding priority,
* as when methods of this class are optimized by the runtime
* compiler, some or all checks (if any) may be elided. Hence, the
* caller must not rely on the checks and corresponding
* exceptions!
*
* @throws RuntimeException if any of the arguments is invalid
*
* @since 9 * @since 9
*/ */
public void copySwapMemory(Object srcBase, long srcOffset, public void copySwapMemory(Object srcBase, long srcOffset,
Object destBase, long destOffset, Object destBase, long destOffset,
long bytes, long elemSize) { long bytes, long elemSize) {
if (bytes < 0) { copySwapMemoryChecks(srcBase, srcOffset, destBase, destOffset, bytes, elemSize);
throw new IllegalArgumentException();
}
if (elemSize != 2 && elemSize != 4 && elemSize != 8) {
throw new IllegalArgumentException();
}
if (bytes % elemSize != 0) {
throw new IllegalArgumentException();
}
if ((srcBase == null && srcOffset == 0) ||
(destBase == null && destOffset == 0)) {
throw new NullPointerException();
}
// Must be off-heap, or primitive heap arrays
if (srcBase != null && (srcOffset < 0 || !isPrimitiveArray(srcBase.getClass()))) {
throw new IllegalArgumentException();
}
if (destBase != null && (destOffset < 0 || !isPrimitiveArray(destBase.getClass()))) {
throw new IllegalArgumentException();
}
// Sanity check size and offsets on 32-bit platforms. Most
// significant 32 bits must be zero.
if (ADDRESS_SIZE == 4 &&
(bytes >>> 32 != 0 || srcOffset >>> 32 != 0 || destOffset >>> 32 != 0)) {
throw new IllegalArgumentException();
}
if (bytes == 0) { if (bytes == 0) {
return; return;
@ -517,6 +801,22 @@ public final class Unsafe {
copySwapMemory0(srcBase, srcOffset, destBase, destOffset, bytes, elemSize); copySwapMemory0(srcBase, srcOffset, destBase, destOffset, bytes, elemSize);
} }
private void copySwapMemoryChecks(Object srcBase, long srcOffset,
Object destBase, long destOffset,
long bytes, long elemSize) {
checkSize(bytes);
if (elemSize != 2 && elemSize != 4 && elemSize != 8) {
throw invalidInput();
}
if (bytes % elemSize != 0) {
throw invalidInput();
}
checkPrimitivePointer(srcBase, srcOffset);
checkPrimitivePointer(destBase, destOffset);
}
/** /**
* Copies all elements from one block of memory to another block, byte swapping the * Copies all elements from one block of memory to another block, byte swapping the
* elements on the fly. * elements on the fly.
@ -535,9 +835,40 @@ public final class Unsafe {
* #allocateMemory} or {@link #reallocateMemory}. The address passed to * #allocateMemory} or {@link #reallocateMemory}. The address passed to
* this method may be null, in which case no action is taken. * this method may be null, in which case no action is taken.
* *
* <em>Note:</em> It is the resposibility of the caller to make
* sure arguments are checked before the methods are called. While
* some rudimentary checks are performed on the input, the checks
* are best effort and when performance is an overriding priority,
* as when methods of this class are optimized by the runtime
* compiler, some or all checks (if any) may be elided. Hence, the
* caller must not rely on the checks and corresponding
* exceptions!
*
* @throws RuntimeException if any of the arguments is invalid
*
* @see #allocateMemory * @see #allocateMemory
*/ */
public native void freeMemory(long address); public void freeMemory(long address) {
freeMemoryChecks(address);
if (address == 0) {
return;
}
freeMemory0(address);
}
/**
* Validate the arguments to freeMemory
*
* @throws RuntimeException if the arguments are invalid
* (<em>Note:</em> after optimization, invalid inputs may
* go undetected, which will lead to unpredictable
* behavior)
*/
private void freeMemoryChecks(long address) {
checkPointer(null, address);
}
/// random queries /// random queries
@ -546,7 +877,7 @@ public final class Unsafe {
* {@link #staticFieldOffset}, {@link #objectFieldOffset}, * {@link #staticFieldOffset}, {@link #objectFieldOffset},
* or {@link #arrayBaseOffset}. * or {@link #arrayBaseOffset}.
*/ */
public static final int INVALID_FIELD_OFFSET = -1; public static final int INVALID_FIELD_OFFSET = -1;
/** /**
* Reports the location of a given field in the storage allocation of its * Reports the location of a given field in the storage allocation of its
@ -566,7 +897,13 @@ public final class Unsafe {
* must preserve all bits of static field offsets. * must preserve all bits of static field offsets.
* @see #getInt(Object, long) * @see #getInt(Object, long)
*/ */
public native long objectFieldOffset(Field f); public long objectFieldOffset(Field f) {
if (f == null) {
throw new NullPointerException();
}
return objectFieldOffset0(f);
}
/** /**
* Reports the location of a given static field, in conjunction with {@link * Reports the location of a given static field, in conjunction with {@link
@ -585,7 +922,13 @@ public final class Unsafe {
* this method reports its result as a long value. * this method reports its result as a long value.
* @see #getInt(Object, long) * @see #getInt(Object, long)
*/ */
public native long staticFieldOffset(Field f); public long staticFieldOffset(Field f) {
if (f == null) {
throw new NullPointerException();
}
return staticFieldOffset0(f);
}
/** /**
* Reports the location of a given static field, in conjunction with {@link * Reports the location of a given static field, in conjunction with {@link
@ -597,7 +940,13 @@ public final class Unsafe {
* not be used in any way except as argument to the get and put routines in * not be used in any way except as argument to the get and put routines in
* this class. * this class.
*/ */
public native Object staticFieldBase(Field f); public Object staticFieldBase(Field f) {
if (f == null) {
throw new NullPointerException();
}
return staticFieldBase0(f);
}
/** /**
* Detects if the given class may need to be initialized. This is often * Detects if the given class may need to be initialized. This is often
@ -605,14 +954,26 @@ public final class Unsafe {
* class. * class.
* @return false only if a call to {@code ensureClassInitialized} would have no effect * @return false only if a call to {@code ensureClassInitialized} would have no effect
*/ */
public native boolean shouldBeInitialized(Class<?> c); public boolean shouldBeInitialized(Class<?> c) {
if (c == null) {
throw new NullPointerException();
}
return shouldBeInitialized0(c);
}
/** /**
* Ensures the given class has been initialized. This is often * Ensures the given class has been initialized. This is often
* needed in conjunction with obtaining the static field base of a * needed in conjunction with obtaining the static field base of a
* class. * class.
*/ */
public native void ensureClassInitialized(Class<?> c); public void ensureClassInitialized(Class<?> c) {
if (c == null) {
throw new NullPointerException();
}
ensureClassInitialized0(c);
}
/** /**
* Reports the offset of the first element in the storage allocation of a * Reports the offset of the first element in the storage allocation of a
@ -624,7 +985,14 @@ public final class Unsafe {
* @see #getInt(Object, long) * @see #getInt(Object, long)
* @see #putInt(Object, long, int) * @see #putInt(Object, long, int)
*/ */
public native int arrayBaseOffset(Class<?> arrayClass); public int arrayBaseOffset(Class<?> arrayClass) {
if (arrayClass == null) {
throw new NullPointerException();
}
return arrayBaseOffset0(arrayClass);
}
/** The value of {@code arrayBaseOffset(boolean[].class)} */ /** The value of {@code arrayBaseOffset(boolean[].class)} */
public static final int ARRAY_BOOLEAN_BASE_OFFSET public static final int ARRAY_BOOLEAN_BASE_OFFSET
@ -673,7 +1041,14 @@ public final class Unsafe {
* @see #getInt(Object, long) * @see #getInt(Object, long)
* @see #putInt(Object, long, int) * @see #putInt(Object, long, int)
*/ */
public native int arrayIndexScale(Class<?> arrayClass); public int arrayIndexScale(Class<?> arrayClass) {
if (arrayClass == null) {
throw new NullPointerException();
}
return arrayIndexScale0(arrayClass);
}
/** The value of {@code arrayIndexScale(boolean[].class)} */ /** The value of {@code arrayIndexScale(boolean[].class)} */
public static final int ARRAY_BOOLEAN_INDEX_SCALE public static final int ARRAY_BOOLEAN_INDEX_SCALE
@ -717,10 +1092,12 @@ public final class Unsafe {
* other primitive types (as stored in native memory blocks) is determined * other primitive types (as stored in native memory blocks) is determined
* fully by their information content. * fully by their information content.
*/ */
public native int addressSize(); public int addressSize() {
return ADDRESS_SIZE;
}
/** The value of {@code addressSize()} */ /** The value of {@code addressSize()} */
public static final int ADDRESS_SIZE = theUnsafe.addressSize(); public static final int ADDRESS_SIZE = theUnsafe.addressSize0();
/** /**
* Reports the size in bytes of a native memory page (whatever that is). * Reports the size in bytes of a native memory page (whatever that is).
@ -735,9 +1112,22 @@ public final class Unsafe {
* Tells the VM to define a class, without security checks. By default, the * Tells the VM to define a class, without security checks. By default, the
* class loader and protection domain come from the caller's class. * class loader and protection domain come from the caller's class.
*/ */
public native Class<?> defineClass(String name, byte[] b, int off, int len, public Class<?> defineClass(String name, byte[] b, int off, int len,
ClassLoader loader, ClassLoader loader,
ProtectionDomain protectionDomain); ProtectionDomain protectionDomain) {
if (b == null) {
throw new NullPointerException();
}
if (len < 0) {
throw new ArrayIndexOutOfBoundsException();
}
return defineClass0(name, b, off, len, loader, protectionDomain);
}
public native Class<?> defineClass0(String name, byte[] b, int off, int len,
ClassLoader loader,
ProtectionDomain protectionDomain);
/** /**
* Defines a class but does not make it known to the class loader or system dictionary. * Defines a class but does not make it known to the class loader or system dictionary.
@ -755,7 +1145,13 @@ public final class Unsafe {
* @param data bytes of a class file * @param data bytes of a class file
* @param cpPatches where non-null entries exist, they replace corresponding CP entries in data * @param cpPatches where non-null entries exist, they replace corresponding CP entries in data
*/ */
public native Class<?> defineAnonymousClass(Class<?> hostClass, byte[] data, Object[] cpPatches); public Class<?> defineAnonymousClass(Class<?> hostClass, byte[] data, Object[] cpPatches) {
if (hostClass == null || data == null) {
throw new NullPointerException();
}
return defineAnonymousClass0(hostClass, data, cpPatches);
}
/** /**
* Allocates an instance but does not run any constructor. * Allocates an instance but does not run any constructor.
@ -765,6 +1161,59 @@ public final class Unsafe {
public native Object allocateInstance(Class<?> cls) public native Object allocateInstance(Class<?> cls)
throws InstantiationException; throws InstantiationException;
/**
* Allocates an array of a given type, but does not do zeroing.
* <p>
* This method should only be used in the very rare cases where a high-performance code
* overwrites the destination array completely, and compilers cannot assist in zeroing elimination.
* In an overwhelming majority of cases, a normal Java allocation should be used instead.
* <p>
* Users of this method are <b>required</b> to overwrite the initial (garbage) array contents
* before allowing untrusted code, or code in other threads, to observe the reference
* to the newly allocated array. In addition, the publication of the array reference must be
* safe according to the Java Memory Model requirements.
* <p>
* The safest approach to deal with an uninitialized array is to keep the reference to it in local
* variable at least until the initialization is complete, and then publish it <b>once</b>, either
* by writing it to a <em>volatile</em> field, or storing it into a <em>final</em> field in constructor,
* or issuing a {@link #storeFence} before publishing the reference.
* <p>
* @implnote This method can only allocate primitive arrays, to avoid garbage reference
* elements that could break heap integrity.
*
* @param componentType array component type to allocate
* @param length array size to allocate
* @throws IllegalArgumentException if component type is null, or not a primitive class;
* or the length is negative
*/
public Object allocateUninitializedArray(Class<?> componentType, int length) {
if (componentType == null) {
throw new IllegalArgumentException("Component type is null");
}
if (!componentType.isPrimitive()) {
throw new IllegalArgumentException("Component type is not primitive");
}
if (length < 0) {
throw new IllegalArgumentException("Negative length");
}
return allocateUninitializedArray0(componentType, length);
}
@HotSpotIntrinsicCandidate
private Object allocateUninitializedArray0(Class<?> componentType, int length) {
// These fallbacks provide zeroed arrays, but intrinsic is not required to
// return the zeroed arrays.
if (componentType == byte.class) return new byte[length];
if (componentType == boolean.class) return new boolean[length];
if (componentType == short.class) return new short[length];
if (componentType == char.class) return new char[length];
if (componentType == int.class) return new int[length];
if (componentType == float.class) return new float[length];
if (componentType == long.class) return new long[length];
if (componentType == double.class) return new double[length];
return null;
}
/** Throws the exception without telling the verifier. */ /** Throws the exception without telling the verifier. */
public native void throwException(Throwable ee); public native void throwException(Throwable ee);
@ -1290,7 +1739,13 @@ public final class Unsafe {
* @return the number of samples actually retrieved; or -1 * @return the number of samples actually retrieved; or -1
* if the load average is unobtainable. * if the load average is unobtainable.
*/ */
public native int getLoadAverage(double[] loadavg, int nelems); public int getLoadAverage(double[] loadavg, int nelems) {
if (nelems < 0 || nelems > 3 || nelems > loadavg.length) {
throw new ArrayIndexOutOfBoundsException();
}
return getLoadAverage0(loadavg, nelems);
}
// The following contain CAS-based Java implementations used on // The following contain CAS-based Java implementations used on
// platforms not supporting native instructions // platforms not supporting native instructions
@ -1718,9 +2173,6 @@ public final class Unsafe {
} }
// JVM interface methods // JVM interface methods
private native boolean unalignedAccess0();
private native boolean isBigEndian0();
// BE is true iff the native endianness of this platform is big. // BE is true iff the native endianness of this platform is big.
private static final boolean BE = theUnsafe.isBigEndian0(); private static final boolean BE = theUnsafe.isBigEndian0();
@ -1820,4 +2272,26 @@ public final class Unsafe {
private static short convEndian(boolean big, short n) { return big == BE ? n : Short.reverseBytes(n) ; } private static short convEndian(boolean big, short n) { return big == BE ? n : Short.reverseBytes(n) ; }
private static int convEndian(boolean big, int n) { return big == BE ? n : Integer.reverseBytes(n) ; } private static int convEndian(boolean big, int n) { return big == BE ? n : Integer.reverseBytes(n) ; }
private static long convEndian(boolean big, long n) { return big == BE ? n : Long.reverseBytes(n) ; } private static long convEndian(boolean big, long n) { return big == BE ? n : Long.reverseBytes(n) ; }
private native long allocateMemory0(long bytes);
private native long reallocateMemory0(long address, long bytes);
private native void freeMemory0(long address);
private native void setMemory0(Object o, long offset, long bytes, byte value);
@HotSpotIntrinsicCandidate
private native void copyMemory0(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes);
private native void copySwapMemory0(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes, long elemSize);
private native long objectFieldOffset0(Field f);
private native long staticFieldOffset0(Field f);
private native Object staticFieldBase0(Field f);
private native boolean shouldBeInitialized0(Class<?> c);
private native void ensureClassInitialized0(Class<?> c);
private native int arrayBaseOffset0(Class<?> arrayClass);
private native int arrayIndexScale0(Class<?> arrayClass);
private native int addressSize0();
private native Class<?> defineAnonymousClass0(Class<?> hostClass, byte[] data, Object[] cpPatches);
private native int getLoadAverage0(double[] loadavg, int nelems);
private native boolean unalignedAccess0();
private native boolean isBigEndian0();
} }

@ -195,7 +195,7 @@ public class ClassReader {
public ClassReader(final byte[] b, final int off, final int len) { public ClassReader(final byte[] b, final int off, final int len) {
this.b = b; this.b = b;
// checks the class version // checks the class version
if (readShort(off + 6) > Opcodes.V1_8) { if (readShort(off + 6) > Opcodes.V1_9) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
// parses the constant pool // parses the constant pool
@ -1199,7 +1199,14 @@ public class ClassReader {
if (labels[label] == null) { if (labels[label] == null) {
readLabel(label, labels).status |= Label.DEBUG; readLabel(label, labels).status |= Label.DEBUG;
} }
labels[label].line = readUnsignedShort(v + 12); Label l = labels[label];
while (l.line > 0) {
if (l.next == null) {
l.next = new Label();
}
l = l.next;
}
l.line = readUnsignedShort(v + 12);
v += 4; v += 4;
} }
} }
@ -1314,9 +1321,15 @@ public class ClassReader {
// visits the label and line number for this offset, if any // visits the label and line number for this offset, if any
Label l = labels[offset]; Label l = labels[offset];
if (l != null) { if (l != null) {
Label next = l.next;
l.next = null;
mv.visitLabel(l); mv.visitLabel(l);
if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) { if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) {
mv.visitLineNumber(l.line, l); mv.visitLineNumber(l.line, l);
while (next != null) {
mv.visitLineNumber(next.line, l);
next = next.next;
}
} }
} }
@ -1857,8 +1870,7 @@ public class ClassReader {
v += 2; v += 2;
break; break;
case 'B': // pointer to CONSTANT_Byte case 'B': // pointer to CONSTANT_Byte
av.visit(name, av.visit(name, (byte) readInt(items[readUnsignedShort(v)]));
(byte) readInt(items[readUnsignedShort(v)]));
v += 2; v += 2;
break; break;
case 'Z': // pointer to CONSTANT_Boolean case 'Z': // pointer to CONSTANT_Boolean
@ -1868,13 +1880,11 @@ public class ClassReader {
v += 2; v += 2;
break; break;
case 'S': // pointer to CONSTANT_Short case 'S': // pointer to CONSTANT_Short
av.visit(name, av.visit(name, (short) readInt(items[readUnsignedShort(v)]));
(short) readInt(items[readUnsignedShort(v)]));
v += 2; v += 2;
break; break;
case 'C': // pointer to CONSTANT_Char case 'C': // pointer to CONSTANT_Char
av.visit(name, av.visit(name, (char) readInt(items[readUnsignedShort(v)]));
(char) readInt(items[readUnsignedShort(v)]));
v += 2; v += 2;
break; break;
case 's': // pointer to CONSTANT_Utf8 case 's': // pointer to CONSTANT_Utf8
@ -2515,11 +2525,12 @@ public class ClassReader {
int tag = readByte(index); int tag = readByte(index);
int[] items = this.items; int[] items = this.items;
int cpIndex = items[readUnsignedShort(index + 1)]; int cpIndex = items[readUnsignedShort(index + 1)];
boolean itf = b[cpIndex - 1] == ClassWriter.IMETH;
String owner = readClass(cpIndex, buf); String owner = readClass(cpIndex, buf);
cpIndex = items[readUnsignedShort(cpIndex + 2)]; cpIndex = items[readUnsignedShort(cpIndex + 2)];
String name = readUTF8(cpIndex, buf); String name = readUTF8(cpIndex, buf);
String desc = readUTF8(cpIndex + 2, buf); String desc = readUTF8(cpIndex + 2, buf);
return new Handle(tag, owner, name, desc); return new Handle(tag, owner, name, desc, itf);
} }
} }
} }

@ -1081,7 +1081,7 @@ public class ClassWriter extends ClassVisitor {
} }
} else if (cst instanceof Handle) { } else if (cst instanceof Handle) {
Handle h = (Handle) cst; Handle h = (Handle) cst;
return newHandleItem(h.tag, h.owner, h.name, h.desc); return newHandleItem(h.tag, h.owner, h.name, h.desc, h.itf);
} else { } else {
throw new IllegalArgumentException("value " + cst); throw new IllegalArgumentException("value " + cst);
} }
@ -1216,10 +1216,12 @@ public class ClassWriter extends ClassVisitor {
* the name of the field or method. * the name of the field or method.
* @param desc * @param desc
* the descriptor of the field or method. * the descriptor of the field or method.
* @param itf
* true if the owner is an interface.
* @return a new or an already existing method type reference item. * @return a new or an already existing method type reference item.
*/ */
Item newHandleItem(final int tag, final String owner, final String name, Item newHandleItem(final int tag, final String owner, final String name,
final String desc) { final String desc, final boolean itf) {
key4.set(HANDLE_BASE + tag, owner, name, desc); key4.set(HANDLE_BASE + tag, owner, name, desc);
Item result = get(key4); Item result = get(key4);
if (result == null) { if (result == null) {
@ -1228,8 +1230,7 @@ public class ClassWriter extends ClassVisitor {
} else { } else {
put112(HANDLE, put112(HANDLE,
tag, tag,
newMethod(owner, name, desc, newMethod(owner, name, desc, itf));
tag == Opcodes.H_INVOKEINTERFACE));
} }
result = new Item(index++, key4); result = new Item(index++, key4);
put(result); put(result);
@ -1259,10 +1260,44 @@ public class ClassWriter extends ClassVisitor {
* the descriptor of the field or method. * the descriptor of the field or method.
* @return the index of a new or already existing method type reference * @return the index of a new or already existing method type reference
* item. * item.
*
* @deprecated this method is superseded by
* {@link #newHandle(int, String, String, String, boolean)}.
*/ */
@Deprecated
public int newHandle(final int tag, final String owner, final String name, public int newHandle(final int tag, final String owner, final String name,
final String desc) { final String desc) {
return newHandleItem(tag, owner, name, desc).index; return newHandle(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE);
}
/**
* Adds a handle to the constant pool of the class being build. Does nothing
* if the constant pool already contains a similar item. <i>This method is
* intended for {@link Attribute} sub classes, and is normally not needed by
* class generators or adapters.</i>
*
* @param tag
* the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
* {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
* {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
* {@link Opcodes#H_INVOKESTATIC},
* {@link Opcodes#H_INVOKESPECIAL},
* {@link Opcodes#H_NEWINVOKESPECIAL} or
* {@link Opcodes#H_INVOKEINTERFACE}.
* @param owner
* the internal name of the field or method owner class.
* @param name
* the name of the field or method.
* @param desc
* the descriptor of the field or method.
* @param itf
* true if the owner is an interface.
* @return the index of a new or already existing method type reference
* item.
*/
public int newHandle(final int tag, final String owner, final String name,
final String desc, final boolean itf) {
return newHandleItem(tag, owner, name, desc, itf).index;
} }
/** /**
@ -1294,7 +1329,7 @@ public class ClassWriter extends ClassVisitor {
int hashCode = bsm.hashCode(); int hashCode = bsm.hashCode();
bootstrapMethods.putShort(newHandle(bsm.tag, bsm.owner, bsm.name, bootstrapMethods.putShort(newHandle(bsm.tag, bsm.owner, bsm.name,
bsm.desc)); bsm.desc, bsm.isInterface()));
int argsLength = bsmArgs.length; int argsLength = bsmArgs.length;
bootstrapMethods.putShort(argsLength); bootstrapMethods.putShort(argsLength);

@ -192,7 +192,7 @@ final class Frame {
private static final int LOCAL = 0x2000000; private static final int LOCAL = 0x2000000;
/** /**
* Kind of the types that are relative to the stack of an input stack * Kind of the the types that are relative to the stack of an input stack
* map frame. The value of such types is a position relatively to the top of * map frame. The value of such types is a position relatively to the top of
* this stack. * this stack.
*/ */

@ -93,6 +93,12 @@ public final class Handle {
*/ */
final String desc; final String desc;
/**
* Indicate if the owner is an interface or not.
*/
final boolean itf;
/** /**
* Constructs a new field or method handle. * Constructs a new field or method handle.
* *
@ -113,12 +119,44 @@ public final class Handle {
* @param desc * @param desc
* the descriptor of the field or method designated by this * the descriptor of the field or method designated by this
* handle. * handle.
*
* @deprecated this constructor has been superseded
* by {@link #Handle(int, String, String, String, boolean)}.
*/ */
@Deprecated
public Handle(int tag, String owner, String name, String desc) { public Handle(int tag, String owner, String name, String desc) {
this(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE);
}
/**
* Constructs a new field or method handle.
*
* @param tag
* the kind of field or method designated by this Handle. Must be
* {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
* {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
* {@link Opcodes#H_INVOKEVIRTUAL},
* {@link Opcodes#H_INVOKESTATIC},
* {@link Opcodes#H_INVOKESPECIAL},
* {@link Opcodes#H_NEWINVOKESPECIAL} or
* {@link Opcodes#H_INVOKEINTERFACE}.
* @param owner
* the internal name of the class that owns the field or method
* designated by this handle.
* @param name
* the name of the field or method designated by this handle.
* @param desc
* the descriptor of the field or method designated by this
* handle.
* @param itf
* true if the owner is an interface.
*/
public Handle(int tag, String owner, String name, String desc, boolean itf) {
this.tag = tag; this.tag = tag;
this.owner = owner; this.owner = owner;
this.name = name; this.name = name;
this.desc = desc; this.desc = desc;
this.itf = itf;
} }
/** /**
@ -164,6 +202,17 @@ public final class Handle {
return desc; return desc;
} }
/**
* Returns true if the owner of the field or method designated
* by this handle is an interface.
*
* @return true if the owner of the field or method designated
* by this handle is an interface.
*/
public boolean isInterface() {
return itf;
}
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj == this) { if (obj == this) {
@ -173,13 +222,13 @@ public final class Handle {
return false; return false;
} }
Handle h = (Handle) obj; Handle h = (Handle) obj;
return tag == h.tag && owner.equals(h.owner) && name.equals(h.name) return tag == h.tag && itf == h.itf && owner.equals(h.owner)
&& desc.equals(h.desc); && name.equals(h.name) && desc.equals(h.desc);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return tag + owner.hashCode() * name.hashCode() * desc.hashCode(); return tag + (itf? 64: 0) + owner.hashCode() * name.hashCode() * desc.hashCode();
} }
/** /**
@ -187,13 +236,16 @@ public final class Handle {
* representation is: * representation is:
* *
* <pre> * <pre>
* for a reference to a class:
* owner '.' name desc ' ' '(' tag ')' * owner '.' name desc ' ' '(' tag ')'
* for a reference to an interface:
* owner '.' name desc ' ' '(' tag ' ' itf ')'
* </pre> * </pre>
* *
* . As this format is unambiguous, it can be parsed if necessary. * . As this format is unambiguous, it can be parsed if necessary.
*/ */
@Override @Override
public String toString() { public String toString() {
return owner + '.' + name + desc + " (" + tag + ')'; return owner + '.' + name + desc + " (" + tag + (itf? " itf": "") + ')';
} }
} }

@ -160,7 +160,11 @@ public class Label {
int status; int status;
/** /**
* The line number corresponding to this label, if known. * The line number corresponding to this label, if known. If there are
* several lines, each line is stored in a separate label, all linked via
* their next field (these links are created in ClassReader and removed just
* before visitLabel is called, so that this does not impact the rest of the
* code).
*/ */
int line; int line;
@ -268,7 +272,8 @@ public class Label {
* The next basic block in the basic block stack. This stack is used in the * The next basic block in the basic block stack. This stack is used in the
* main loop of the fix point algorithm used in the second step of the * main loop of the fix point algorithm used in the second step of the
* control flow analysis algorithms. It is also used in * control flow analysis algorithms. It is also used in
* {@link #visitSubroutine} to avoid using a recursive method. * {@link #visitSubroutine} to avoid using a recursive method, and in
* ClassReader to temporarily store multiple source lines for a label.
* *
* @see MethodWriter#visitMaxs * @see MethodWriter#visitMaxs
*/ */

@ -62,15 +62,16 @@ package jdk.internal.org.objectweb.asm;
* A visitor to visit a Java method. The methods of this class must be called in * A visitor to visit a Java method. The methods of this class must be called in
* the following order: ( <tt>visitParameter</tt> )* [ * the following order: ( <tt>visitParameter</tt> )* [
* <tt>visitAnnotationDefault</tt> ] ( <tt>visitAnnotation</tt> | * <tt>visitAnnotationDefault</tt> ] ( <tt>visitAnnotation</tt> |
* <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* [ * <tt>visitParameterAnnotation</tt> <tt>visitTypeAnnotation</tt> |
* <tt>visitCode</tt> ( <tt>visitFrame</tt> | <tt>visit<i>X</i>Insn</tt> | * <tt>visitAttribute</tt> )* [ <tt>visitCode</tt> ( <tt>visitFrame</tt> |
* <tt>visitLabel</tt> | <tt>visitInsnAnnotation</tt> | * <tt>visit<i>X</i>Insn</tt> | <tt>visitLabel</tt> |
* <tt>visitTryCatchBlock</tt> | <tt>visitTryCatchBlockAnnotation</tt> | * <tt>visitInsnAnnotation</tt> | <tt>visitTryCatchBlock</tt> |
* <tt>visitLocalVariable</tt> | <tt>visitLocalVariableAnnotation</tt> | * <tt>visitTryCatchAnnotation</tt> | <tt>visitLocalVariable</tt> |
* <tt>visitLineNumber</tt> )* <tt>visitMaxs</tt> ] <tt>visitEnd</tt>. In * <tt>visitLocalVariableAnnotation</tt> | <tt>visitLineNumber</tt> )*
* addition, the <tt>visit<i>X</i>Insn</tt> and <tt>visitLabel</tt> methods must * <tt>visitMaxs</tt> ] <tt>visitEnd</tt>. In addition, the
* be called in the sequential order of the bytecode instructions of the visited * <tt>visit<i>X</i>Insn</tt> and <tt>visitLabel</tt> methods must be called in
* code, <tt>visitInsnAnnotation</tt> must be called <i>after</i> the annotated * the sequential order of the bytecode instructions of the visited code,
* <tt>visitInsnAnnotation</tt> must be called <i>after</i> the annotated
* instruction, <tt>visitTryCatchBlock</tt> must be called <i>before</i> the * instruction, <tt>visitTryCatchBlock</tt> must be called <i>before</i> the
* labels passed as arguments have been visited, * labels passed as arguments have been visited,
* <tt>visitTryCatchBlockAnnotation</tt> must be called <i>after</i> the * <tt>visitTryCatchBlockAnnotation</tt> must be called <i>after</i> the

@ -2061,7 +2061,7 @@ class MethodWriter extends MethodVisitor {
} }
int size = 8; int size = 8;
if (code.length > 0) { if (code.length > 0) {
if (code.length > 65536) { if (code.length > 65535) {
throw new RuntimeException("Method code too large!"); throw new RuntimeException("Method code too large!");
} }
cw.newUTF8("Code"); cw.newUTF8("Code");
@ -2735,11 +2735,13 @@ class MethodWriter extends MethodVisitor {
l = l.successor; l = l.successor;
} }
// Update the offsets in the uninitialized types // Update the offsets in the uninitialized types
for (i = 0; i < cw.typeTable.length; ++i) { if (cw.typeTable != null) {
Item item = cw.typeTable[i]; for (i = 0; i < cw.typeTable.length; ++i) {
if (item != null && item.type == ClassWriter.TYPE_UNINIT) { Item item = cw.typeTable[i];
item.intVal = getNewOffset(allIndexes, allSizes, 0, if (item != null && item.type == ClassWriter.TYPE_UNINIT) {
item.intVal); item.intVal = getNewOffset(allIndexes, allSizes, 0,
item.intVal);
}
} }
} }
// The stack map frames are not serialized yet, so we don't need // The stack map frames are not serialized yet, so we don't need

@ -87,6 +87,7 @@ public interface Opcodes {
int V1_6 = 0 << 16 | 50; int V1_6 = 0 << 16 | 50;
int V1_7 = 0 << 16 | 51; int V1_7 = 0 << 16 | 51;
int V1_8 = 0 << 16 | 52; int V1_8 = 0 << 16 | 52;
int V1_9 = 0 << 16 | 53;
// access flags // access flags

@ -654,7 +654,7 @@ public class Type {
* @return the descriptor corresponding to this Java type. * @return the descriptor corresponding to this Java type.
*/ */
public String getDescriptor() { public String getDescriptor() {
StringBuffer buf = new StringBuffer(); StringBuilder buf = new StringBuilder();
getDescriptor(buf); getDescriptor(buf);
return buf.toString(); return buf.toString();
} }
@ -672,7 +672,7 @@ public class Type {
*/ */
public static String getMethodDescriptor(final Type returnType, public static String getMethodDescriptor(final Type returnType,
final Type... argumentTypes) { final Type... argumentTypes) {
StringBuffer buf = new StringBuffer(); StringBuilder buf = new StringBuilder();
buf.append('('); buf.append('(');
for (int i = 0; i < argumentTypes.length; ++i) { for (int i = 0; i < argumentTypes.length; ++i) {
argumentTypes[i].getDescriptor(buf); argumentTypes[i].getDescriptor(buf);
@ -689,7 +689,7 @@ public class Type {
* @param buf * @param buf
* the string buffer to which the descriptor must be appended. * the string buffer to which the descriptor must be appended.
*/ */
private void getDescriptor(final StringBuffer buf) { private void getDescriptor(final StringBuilder buf) {
if (this.buf == null) { if (this.buf == null) {
// descriptor is in byte 3 of 'off' for primitive types (buf == // descriptor is in byte 3 of 'off' for primitive types (buf ==
// null) // null)
@ -729,7 +729,7 @@ public class Type {
* @return the descriptor corresponding to the given class. * @return the descriptor corresponding to the given class.
*/ */
public static String getDescriptor(final Class<?> c) { public static String getDescriptor(final Class<?> c) {
StringBuffer buf = new StringBuffer(); StringBuilder buf = new StringBuilder();
getDescriptor(buf, c); getDescriptor(buf, c);
return buf.toString(); return buf.toString();
} }
@ -743,7 +743,7 @@ public class Type {
*/ */
public static String getConstructorDescriptor(final Constructor<?> c) { public static String getConstructorDescriptor(final Constructor<?> c) {
Class<?>[] parameters = c.getParameterTypes(); Class<?>[] parameters = c.getParameterTypes();
StringBuffer buf = new StringBuffer(); StringBuilder buf = new StringBuilder();
buf.append('('); buf.append('(');
for (int i = 0; i < parameters.length; ++i) { for (int i = 0; i < parameters.length; ++i) {
getDescriptor(buf, parameters[i]); getDescriptor(buf, parameters[i]);
@ -760,7 +760,7 @@ public class Type {
*/ */
public static String getMethodDescriptor(final Method m) { public static String getMethodDescriptor(final Method m) {
Class<?>[] parameters = m.getParameterTypes(); Class<?>[] parameters = m.getParameterTypes();
StringBuffer buf = new StringBuffer(); StringBuilder buf = new StringBuilder();
buf.append('('); buf.append('(');
for (int i = 0; i < parameters.length; ++i) { for (int i = 0; i < parameters.length; ++i) {
getDescriptor(buf, parameters[i]); getDescriptor(buf, parameters[i]);
@ -778,7 +778,7 @@ public class Type {
* @param c * @param c
* the class whose descriptor must be computed. * the class whose descriptor must be computed.
*/ */
private static void getDescriptor(final StringBuffer buf, final Class<?> c) { private static void getDescriptor(final StringBuilder buf, final Class<?> c) {
Class<?> d = c; Class<?> d = c;
while (true) { while (true) {
if (d.isPrimitive()) { if (d.isPrimitive()) {

@ -71,25 +71,25 @@ public class TypePath {
* A type path step that steps into the element type of an array type. See * A type path step that steps into the element type of an array type. See
* {@link #getStep getStep}. * {@link #getStep getStep}.
*/ */
public static final int ARRAY_ELEMENT = 0; public final static int ARRAY_ELEMENT = 0;
/** /**
* A type path step that steps into the nested type of a class type. See * A type path step that steps into the nested type of a class type. See
* {@link #getStep getStep}. * {@link #getStep getStep}.
*/ */
public static final int INNER_TYPE = 1; public final static int INNER_TYPE = 1;
/** /**
* A type path step that steps into the bound of a wildcard type. See * A type path step that steps into the bound of a wildcard type. See
* {@link #getStep getStep}. * {@link #getStep getStep}.
*/ */
public static final int WILDCARD_BOUND = 2; public final static int WILDCARD_BOUND = 2;
/** /**
* A type path step that steps into a type argument of a generic type. See * A type path step that steps into a type argument of a generic type. See
* {@link #getStep getStep}. * {@link #getStep getStep}.
*/ */
public static final int TYPE_ARGUMENT = 3; public final static int TYPE_ARGUMENT = 3;
/** /**
* The byte array where the path is stored, in Java class file format. * The byte array where the path is stored, in Java class file format.

@ -74,133 +74,133 @@ public class TypeReference {
* The sort of type references that target a type parameter of a generic * The sort of type references that target a type parameter of a generic
* class. See {@link #getSort getSort}. * class. See {@link #getSort getSort}.
*/ */
public static final int CLASS_TYPE_PARAMETER = 0x00; public final static int CLASS_TYPE_PARAMETER = 0x00;
/** /**
* The sort of type references that target a type parameter of a generic * The sort of type references that target a type parameter of a generic
* method. See {@link #getSort getSort}. * method. See {@link #getSort getSort}.
*/ */
public static final int METHOD_TYPE_PARAMETER = 0x01; public final static int METHOD_TYPE_PARAMETER = 0x01;
/** /**
* The sort of type references that target the super class of a class or one * The sort of type references that target the super class of a class or one
* of the interfaces it implements. See {@link #getSort getSort}. * of the interfaces it implements. See {@link #getSort getSort}.
*/ */
public static final int CLASS_EXTENDS = 0x10; public final static int CLASS_EXTENDS = 0x10;
/** /**
* The sort of type references that target a bound of a type parameter of a * The sort of type references that target a bound of a type parameter of a
* generic class. See {@link #getSort getSort}. * generic class. See {@link #getSort getSort}.
*/ */
public static final int CLASS_TYPE_PARAMETER_BOUND = 0x11; public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11;
/** /**
* The sort of type references that target a bound of a type parameter of a * The sort of type references that target a bound of a type parameter of a
* generic method. See {@link #getSort getSort}. * generic method. See {@link #getSort getSort}.
*/ */
public static final int METHOD_TYPE_PARAMETER_BOUND = 0x12; public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12;
/** /**
* The sort of type references that target the type of a field. See * The sort of type references that target the type of a field. See
* {@link #getSort getSort}. * {@link #getSort getSort}.
*/ */
public static final int FIELD = 0x13; public final static int FIELD = 0x13;
/** /**
* The sort of type references that target the return type of a method. See * The sort of type references that target the return type of a method. See
* {@link #getSort getSort}. * {@link #getSort getSort}.
*/ */
public static final int METHOD_RETURN = 0x14; public final static int METHOD_RETURN = 0x14;
/** /**
* The sort of type references that target the receiver type of a method. * The sort of type references that target the receiver type of a method.
* See {@link #getSort getSort}. * See {@link #getSort getSort}.
*/ */
public static final int METHOD_RECEIVER = 0x15; public final static int METHOD_RECEIVER = 0x15;
/** /**
* The sort of type references that target the type of a formal parameter of * The sort of type references that target the type of a formal parameter of
* a method. See {@link #getSort getSort}. * a method. See {@link #getSort getSort}.
*/ */
public static final int METHOD_FORMAL_PARAMETER = 0x16; public final static int METHOD_FORMAL_PARAMETER = 0x16;
/** /**
* The sort of type references that target the type of an exception declared * The sort of type references that target the type of an exception declared
* in the throws clause of a method. See {@link #getSort getSort}. * in the throws clause of a method. See {@link #getSort getSort}.
*/ */
public static final int THROWS = 0x17; public final static int THROWS = 0x17;
/** /**
* The sort of type references that target the type of a local variable in a * The sort of type references that target the type of a local variable in a
* method. See {@link #getSort getSort}. * method. See {@link #getSort getSort}.
*/ */
public static final int LOCAL_VARIABLE = 0x40; public final static int LOCAL_VARIABLE = 0x40;
/** /**
* The sort of type references that target the type of a resource variable * The sort of type references that target the type of a resource variable
* in a method. See {@link #getSort getSort}. * in a method. See {@link #getSort getSort}.
*/ */
public static final int RESOURCE_VARIABLE = 0x41; public final static int RESOURCE_VARIABLE = 0x41;
/** /**
* The sort of type references that target the type of the exception of a * The sort of type references that target the type of the exception of a
* 'catch' clause in a method. See {@link #getSort getSort}. * 'catch' clause in a method. See {@link #getSort getSort}.
*/ */
public static final int EXCEPTION_PARAMETER = 0x42; public final static int EXCEPTION_PARAMETER = 0x42;
/** /**
* The sort of type references that target the type declared in an * The sort of type references that target the type declared in an
* 'instanceof' instruction. See {@link #getSort getSort}. * 'instanceof' instruction. See {@link #getSort getSort}.
*/ */
public static final int INSTANCEOF = 0x43; public final static int INSTANCEOF = 0x43;
/** /**
* The sort of type references that target the type of the object created by * The sort of type references that target the type of the object created by
* a 'new' instruction. See {@link #getSort getSort}. * a 'new' instruction. See {@link #getSort getSort}.
*/ */
public static final int NEW = 0x44; public final static int NEW = 0x44;
/** /**
* The sort of type references that target the receiver type of a * The sort of type references that target the receiver type of a
* constructor reference. See {@link #getSort getSort}. * constructor reference. See {@link #getSort getSort}.
*/ */
public static final int CONSTRUCTOR_REFERENCE = 0x45; public final static int CONSTRUCTOR_REFERENCE = 0x45;
/** /**
* The sort of type references that target the receiver type of a method * The sort of type references that target the receiver type of a method
* reference. See {@link #getSort getSort}. * reference. See {@link #getSort getSort}.
*/ */
public static final int METHOD_REFERENCE = 0x46; public final static int METHOD_REFERENCE = 0x46;
/** /**
* The sort of type references that target the type declared in an explicit * The sort of type references that target the type declared in an explicit
* or implicit cast instruction. See {@link #getSort getSort}. * or implicit cast instruction. See {@link #getSort getSort}.
*/ */
public static final int CAST = 0x47; public final static int CAST = 0x47;
/** /**
* The sort of type references that target a type parameter of a generic * The sort of type references that target a type parameter of a generic
* constructor in a constructor call. See {@link #getSort getSort}. * constructor in a constructor call. See {@link #getSort getSort}.
*/ */
public static final int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48; public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
/** /**
* The sort of type references that target a type parameter of a generic * The sort of type references that target a type parameter of a generic
* method in a method call. See {@link #getSort getSort}. * method in a method call. See {@link #getSort getSort}.
*/ */
public static final int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49; public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
/** /**
* The sort of type references that target a type parameter of a generic * The sort of type references that target a type parameter of a generic
* constructor in a constructor reference. See {@link #getSort getSort}. * constructor in a constructor reference. See {@link #getSort getSort}.
*/ */
public static final int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A; public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
/** /**
* The sort of type references that target a type parameter of a generic * The sort of type references that target a type parameter of a generic
* method in a method reference. See {@link #getSort getSort}. * method in a method reference. See {@link #getSort getSort}.
*/ */
public static final int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B; public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
/** /**
* The type reference value in Java class file format. * The type reference value in Java class file format.

@ -388,10 +388,10 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes
} }
break; break;
case PUTFIELD: case PUTFIELD:
popValue();
popValue(); popValue();
if (longOrDouble) { if (longOrDouble) {
popValue(); popValue();
popValue();
} }
break; break;
// case GETFIELD: // case GETFIELD:
@ -619,7 +619,7 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes
} }
/** /**
* Called at the beginning of the method or after super class class call in * Called at the beginning of the method or after super class call in
* the constructor. <br> * the constructor. <br>
* <br> * <br>
* *

@ -0,0 +1,108 @@
/*
* 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.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package jdk.internal.org.objectweb.asm.commons;
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
/**
* An {@link AnnotationVisitor} adapter for type remapping.
*
* @author Eugene Kuleshov
*/
public class AnnotationRemapper extends AnnotationVisitor {
protected final Remapper remapper;
public AnnotationRemapper(final AnnotationVisitor av,
final Remapper remapper) {
this(Opcodes.ASM5, av, remapper);
}
protected AnnotationRemapper(final int api, final AnnotationVisitor av,
final Remapper remapper) {
super(api, av);
this.remapper = remapper;
}
@Override
public void visit(String name, Object value) {
av.visit(name, remapper.mapValue(value));
}
@Override
public void visitEnum(String name, String desc, String value) {
av.visitEnum(name, remapper.mapDesc(desc), value);
}
@Override
public AnnotationVisitor visitAnnotation(String name, String desc) {
AnnotationVisitor v = av.visitAnnotation(name, remapper.mapDesc(desc));
return v == null ? null : (v == av ? this : new AnnotationRemapper(v,
remapper));
}
@Override
public AnnotationVisitor visitArray(String name) {
AnnotationVisitor v = av.visitArray(name);
return v == null ? null : (v == av ? this : new AnnotationRemapper(v,
remapper));
}
}

@ -0,0 +1,161 @@
/*
* 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.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package jdk.internal.org.objectweb.asm.commons;
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.FieldVisitor;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.TypePath;
/**
* A {@link ClassVisitor} for type remapping.
*
* @author Eugene Kuleshov
*/
public class ClassRemapper extends ClassVisitor {
protected final Remapper remapper;
protected String className;
public ClassRemapper(final ClassVisitor cv, final Remapper remapper) {
this(Opcodes.ASM5, cv, remapper);
}
protected ClassRemapper(final int api, final ClassVisitor cv,
final Remapper remapper) {
super(api, cv);
this.remapper = remapper;
}
@Override
public void visit(int version, int access, String name, String signature,
String superName, String[] interfaces) {
this.className = name;
super.visit(version, access, remapper.mapType(name), remapper
.mapSignature(signature, false), remapper.mapType(superName),
interfaces == null ? null : remapper.mapTypes(interfaces));
}
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
visible);
return av == null ? null : createAnnotationRemapper(av);
}
@Override
public AnnotationVisitor visitTypeAnnotation(int typeRef,
TypePath typePath, String desc, boolean visible) {
AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
remapper.mapDesc(desc), visible);
return av == null ? null : createAnnotationRemapper(av);
}
@Override
public FieldVisitor visitField(int access, String name, String desc,
String signature, Object value) {
FieldVisitor fv = super.visitField(access,
remapper.mapFieldName(className, name, desc),
remapper.mapDesc(desc), remapper.mapSignature(signature, true),
remapper.mapValue(value));
return fv == null ? null : createFieldRemapper(fv);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
String newDesc = remapper.mapMethodDesc(desc);
MethodVisitor mv = super.visitMethod(access, remapper.mapMethodName(
className, name, desc), newDesc, remapper.mapSignature(
signature, false),
exceptions == null ? null : remapper.mapTypes(exceptions));
return mv == null ? null : createMethodRemapper(mv);
}
@Override
public void visitInnerClass(String name, String outerName,
String innerName, int access) {
// TODO should innerName be changed?
super.visitInnerClass(remapper.mapType(name), outerName == null ? null
: remapper.mapType(outerName), innerName, access);
}
@Override
public void visitOuterClass(String owner, String name, String desc) {
super.visitOuterClass(remapper.mapType(owner), name == null ? null
: remapper.mapMethodName(owner, name, desc),
desc == null ? null : remapper.mapMethodDesc(desc));
}
protected FieldVisitor createFieldRemapper(FieldVisitor fv) {
return new FieldRemapper(fv, remapper);
}
protected MethodVisitor createMethodRemapper(MethodVisitor mv) {
return new MethodRemapper(mv, remapper);
}
protected AnnotationVisitor createAnnotationRemapper(AnnotationVisitor av) {
return new AnnotationRemapper(av, remapper);
}
}

@ -0,0 +1,100 @@
/*
* 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.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package jdk.internal.org.objectweb.asm.commons;
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
import jdk.internal.org.objectweb.asm.FieldVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.TypePath;
/**
* A {@link FieldVisitor} adapter for type remapping.
*
* @author Eugene Kuleshov
*/
public class FieldRemapper extends FieldVisitor {
private final Remapper remapper;
public FieldRemapper(final FieldVisitor fv, final Remapper remapper) {
this(Opcodes.ASM5, fv, remapper);
}
protected FieldRemapper(final int api, final FieldVisitor fv,
final Remapper remapper) {
super(api, fv);
this.remapper = remapper;
}
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
AnnotationVisitor av = fv.visitAnnotation(remapper.mapDesc(desc),
visible);
return av == null ? null : new AnnotationRemapper(av, remapper);
}
@Override
public AnnotationVisitor visitTypeAnnotation(int typeRef,
TypePath typePath, String desc, boolean visible) {
AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
remapper.mapDesc(desc), visible);
return av == null ? null : new AnnotationRemapper(av, remapper);
}
}

@ -73,7 +73,7 @@ import jdk.internal.org.objectweb.asm.Type;
*/ */
public class InstructionAdapter extends MethodVisitor { public class InstructionAdapter extends MethodVisitor {
public static final Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;"); public final static Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;");
/** /**
* Creates a new {@link InstructionAdapter}. <i>Subclasses must not use this * Creates a new {@link InstructionAdapter}. <i>Subclasses must not use this

@ -104,11 +104,6 @@ public class LocalVariablesSorter extends MethodVisitor {
*/ */
protected int nextLocal; protected int nextLocal;
/**
* Indicates if at least one local variable has moved due to remapping.
*/
private boolean changed;
/** /**
* Creates a new {@link LocalVariablesSorter}. <i>Subclasses must not use * Creates a new {@link LocalVariablesSorter}. <i>Subclasses must not use
* this constructor</i>. Instead, they must use the * this constructor</i>. Instead, they must use the
@ -228,11 +223,6 @@ public class LocalVariablesSorter extends MethodVisitor {
"ClassReader.accept() should be called with EXPAND_FRAMES flag"); "ClassReader.accept() should be called with EXPAND_FRAMES flag");
} }
if (!changed) { // optimization for the case where mapping = identity
mv.visitFrame(type, nLocal, local, nStack, stack);
return;
}
// creates a copy of newLocals // creates a copy of newLocals
Object[] oldLocals = new Object[newLocals.length]; Object[] oldLocals = new Object[newLocals.length];
System.arraycopy(newLocals, 0, oldLocals, 0, oldLocals.length); System.arraycopy(newLocals, 0, oldLocals, 0, oldLocals.length);
@ -328,7 +318,6 @@ public class LocalVariablesSorter extends MethodVisitor {
int local = newLocalMapping(type); int local = newLocalMapping(type);
setLocalType(local, type); setLocalType(local, type);
setFrameLocal(local, t); setFrameLocal(local, t);
changed = true;
return local; return local;
} }
@ -396,9 +385,6 @@ public class LocalVariablesSorter extends MethodVisitor {
} else { } else {
value--; value--;
} }
if (value != var) {
changed = true;
}
return value; return value;
} }

@ -0,0 +1,252 @@
/*
* 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.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package jdk.internal.org.objectweb.asm.commons;
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
import jdk.internal.org.objectweb.asm.Handle;
import jdk.internal.org.objectweb.asm.Label;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.TypePath;
/**
* A {@link LocalVariablesSorter} for type mapping.
*
* @author Eugene Kuleshov
*/
public class MethodRemapper extends MethodVisitor {
protected final Remapper remapper;
public MethodRemapper(final MethodVisitor mv, final Remapper remapper) {
this(Opcodes.ASM5, mv, remapper);
}
protected MethodRemapper(final int api, final MethodVisitor mv,
final Remapper remapper) {
super(api, mv);
this.remapper = remapper;
}
@Override
public AnnotationVisitor visitAnnotationDefault() {
AnnotationVisitor av = super.visitAnnotationDefault();
return av == null ? av : new AnnotationRemapper(av, remapper);
}
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
visible);
return av == null ? av : new AnnotationRemapper(av, remapper);
}
@Override
public AnnotationVisitor visitTypeAnnotation(int typeRef,
TypePath typePath, String desc, boolean visible) {
AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
remapper.mapDesc(desc), visible);
return av == null ? av : new AnnotationRemapper(av, remapper);
}
@Override
public AnnotationVisitor visitParameterAnnotation(int parameter,
String desc, boolean visible) {
AnnotationVisitor av = super.visitParameterAnnotation(parameter,
remapper.mapDesc(desc), visible);
return av == null ? av : new AnnotationRemapper(av, remapper);
}
@Override
public void visitFrame(int type, int nLocal, Object[] local, int nStack,
Object[] stack) {
super.visitFrame(type, nLocal, remapEntries(nLocal, local), nStack,
remapEntries(nStack, stack));
}
private Object[] remapEntries(int n, Object[] entries) {
for (int i = 0; i < n; i++) {
if (entries[i] instanceof String) {
Object[] newEntries = new Object[n];
if (i > 0) {
System.arraycopy(entries, 0, newEntries, 0, i);
}
do {
Object t = entries[i];
newEntries[i++] = t instanceof String ? remapper
.mapType((String) t) : t;
} while (i < n);
return newEntries;
}
}
return entries;
}
@Override
public void visitFieldInsn(int opcode, String owner, String name,
String desc) {
super.visitFieldInsn(opcode, remapper.mapType(owner),
remapper.mapFieldName(owner, name, desc),
remapper.mapDesc(desc));
}
@Deprecated
@Override
public void visitMethodInsn(final int opcode, final String owner,
final String name, final String desc) {
if (api >= Opcodes.ASM5) {
super.visitMethodInsn(opcode, owner, name, desc);
return;
}
doVisitMethodInsn(opcode, owner, name, desc,
opcode == Opcodes.INVOKEINTERFACE);
}
@Override
public void visitMethodInsn(final int opcode, final String owner,
final String name, final String desc, final boolean itf) {
if (api < Opcodes.ASM5) {
super.visitMethodInsn(opcode, owner, name, desc, itf);
return;
}
doVisitMethodInsn(opcode, owner, name, desc, itf);
}
private void doVisitMethodInsn(int opcode, String owner, String name,
String desc, boolean itf) {
// Calling super.visitMethodInsn requires to call the correct version
// depending on this.api (otherwise infinite loops can occur). To
// simplify and to make it easier to automatically remove the backward
// compatibility code, we inline the code of the overridden method here.
// IMPORTANT: THIS ASSUMES THAT visitMethodInsn IS NOT OVERRIDDEN IN
// LocalVariableSorter.
if (mv != null) {
mv.visitMethodInsn(opcode, remapper.mapType(owner),
remapper.mapMethodName(owner, name, desc),
remapper.mapMethodDesc(desc), itf);
}
}
@Override
public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
Object... bsmArgs) {
for (int i = 0; i < bsmArgs.length; i++) {
bsmArgs[i] = remapper.mapValue(bsmArgs[i]);
}
super.visitInvokeDynamicInsn(
remapper.mapInvokeDynamicMethodName(name, desc),
remapper.mapMethodDesc(desc), (Handle) remapper.mapValue(bsm),
bsmArgs);
}
@Override
public void visitTypeInsn(int opcode, String type) {
super.visitTypeInsn(opcode, remapper.mapType(type));
}
@Override
public void visitLdcInsn(Object cst) {
super.visitLdcInsn(remapper.mapValue(cst));
}
@Override
public void visitMultiANewArrayInsn(String desc, int dims) {
super.visitMultiANewArrayInsn(remapper.mapDesc(desc), dims);
}
@Override
public AnnotationVisitor visitInsnAnnotation(int typeRef,
TypePath typePath, String desc, boolean visible) {
AnnotationVisitor av = super.visitInsnAnnotation(typeRef, typePath,
remapper.mapDesc(desc), visible);
return av == null ? av : new AnnotationRemapper(av, remapper);
}
@Override
public void visitTryCatchBlock(Label start, Label end, Label handler,
String type) {
super.visitTryCatchBlock(start, end, handler, type == null ? null
: remapper.mapType(type));
}
@Override
public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
TypePath typePath, String desc, boolean visible) {
AnnotationVisitor av = super.visitTryCatchAnnotation(typeRef, typePath,
remapper.mapDesc(desc), visible);
return av == null ? av : new AnnotationRemapper(av, remapper);
}
@Override
public void visitLocalVariable(String name, String desc, String signature,
Label start, Label end, int index) {
super.visitLocalVariable(name, remapper.mapDesc(desc),
remapper.mapSignature(signature, true), start, end, index);
}
@Override
public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
TypePath typePath, Label[] start, Label[] end, int[] index,
String desc, boolean visible) {
AnnotationVisitor av = super.visitLocalVariableAnnotation(typeRef,
typePath, start, end, index, remapper.mapDesc(desc), visible);
return av == null ? av : new AnnotationRemapper(av, remapper);
}
}

@ -168,17 +168,19 @@ public abstract class Remapper {
Handle h = (Handle) value; Handle h = (Handle) value;
return new Handle(h.getTag(), mapType(h.getOwner()), mapMethodName( return new Handle(h.getTag(), mapType(h.getOwner()), mapMethodName(
h.getOwner(), h.getName(), h.getDesc()), h.getOwner(), h.getName(), h.getDesc()),
mapMethodDesc(h.getDesc())); mapMethodDesc(h.getDesc()), h.isInterface());
} }
return value; return value;
} }
/** /**
* * @param signature
* signature for mapper
* @param typeSignature * @param typeSignature
* true if signature is a FieldTypeSignature, such as the * true if signature is a FieldTypeSignature, such as the
* signature parameter of the ClassVisitor.visitField or * signature parameter of the ClassVisitor.visitField or
* MethodVisitor.visitLocalVariable methods * MethodVisitor.visitLocalVariable methods
* @return signature rewritten as a string
*/ */
public String mapSignature(String signature, boolean typeSignature) { public String mapSignature(String signature, boolean typeSignature) {
if (signature == null) { if (signature == null) {
@ -186,7 +188,7 @@ public abstract class Remapper {
} }
SignatureReader r = new SignatureReader(signature); SignatureReader r = new SignatureReader(signature);
SignatureWriter w = new SignatureWriter(); SignatureWriter w = new SignatureWriter();
SignatureVisitor a = createRemappingSignatureAdapter(w); SignatureVisitor a = createSignatureRemapper(w);
if (typeSignature) { if (typeSignature) {
r.acceptType(a); r.acceptType(a);
} else { } else {
@ -195,9 +197,18 @@ public abstract class Remapper {
return w.toString(); return w.toString();
} }
/**
* @deprecated use {@link #createSignatureRemapper} instead.
*/
@Deprecated
protected SignatureVisitor createRemappingSignatureAdapter( protected SignatureVisitor createRemappingSignatureAdapter(
SignatureVisitor v) { SignatureVisitor v) {
return new RemappingSignatureAdapter(v, this); return new SignatureRemapper(v, this);
}
protected SignatureVisitor createSignatureRemapper(
SignatureVisitor v) {
return createRemappingSignatureAdapter(v);
} }
/** /**
@ -245,6 +256,10 @@ public abstract class Remapper {
/** /**
* Map type name to the new name. Subclasses can override. * Map type name to the new name. Subclasses can override.
*
* @param typeName
* the type name
* @return new name, default implementation is the identity.
*/ */
public String map(String typeName) { public String map(String typeName) {
return typeName; return typeName;

@ -65,8 +65,10 @@ import jdk.internal.org.objectweb.asm.Opcodes;
/** /**
* An {@link AnnotationVisitor} adapter for type remapping. * An {@link AnnotationVisitor} adapter for type remapping.
* *
* //@deprecated use {@link AnnotationRemapper} instead.
* @author Eugene Kuleshov * @author Eugene Kuleshov
*/ */
//@Deprecated
public class RemappingAnnotationAdapter extends AnnotationVisitor { public class RemappingAnnotationAdapter extends AnnotationVisitor {
protected final Remapper remapper; protected final Remapper remapper;

@ -69,8 +69,10 @@ import jdk.internal.org.objectweb.asm.TypePath;
/** /**
* A {@link ClassVisitor} for type remapping. * A {@link ClassVisitor} for type remapping.
* *
* @deprecated use {@link ClassRemapper} instead.
* @author Eugene Kuleshov * @author Eugene Kuleshov
*/ */
@Deprecated
public class RemappingClassAdapter extends ClassVisitor { public class RemappingClassAdapter extends ClassVisitor {
protected final Remapper remapper; protected final Remapper remapper;

@ -67,8 +67,10 @@ import jdk.internal.org.objectweb.asm.TypePath;
/** /**
* A {@link FieldVisitor} adapter for type remapping. * A {@link FieldVisitor} adapter for type remapping.
* *
* @deprecated use {@link FieldRemapper} instead.
* @author Eugene Kuleshov * @author Eugene Kuleshov
*/ */
@Deprecated
public class RemappingFieldAdapter extends FieldVisitor { public class RemappingFieldAdapter extends FieldVisitor {
private final Remapper remapper; private final Remapper remapper;

@ -69,8 +69,10 @@ import jdk.internal.org.objectweb.asm.TypePath;
/** /**
* A {@link LocalVariablesSorter} for type mapping. * A {@link LocalVariablesSorter} for type mapping.
* *
* //@deprecated use {@link MethodRemapper} instead.
* @author Eugene Kuleshov * @author Eugene Kuleshov
*/ */
//@Deprecated
public class RemappingMethodAdapter extends LocalVariablesSorter { public class RemappingMethodAdapter extends LocalVariablesSorter {
protected final Remapper remapper; protected final Remapper remapper;

@ -65,8 +65,10 @@ import jdk.internal.org.objectweb.asm.signature.SignatureVisitor;
/** /**
* A {@link SignatureVisitor} adapter for type mapping. * A {@link SignatureVisitor} adapter for type mapping.
* *
* @deprecated use {@link SignatureRemapper} instead.
* @author Eugene Kuleshov * @author Eugene Kuleshov
*/ */
@Deprecated
public class RemappingSignatureAdapter extends SignatureVisitor { public class RemappingSignatureAdapter extends SignatureVisitor {
private final SignatureVisitor v; private final SignatureVisitor v;

@ -234,7 +234,7 @@ public class SerialVersionUIDAdder extends ClassVisitor {
public void visit(final int version, final int access, final String name, public void visit(final int version, final int access, final String name,
final String signature, final String superName, final String signature, final String superName,
final String[] interfaces) { final String[] interfaces) {
computeSVUID = (access & Opcodes.ACC_INTERFACE) == 0; computeSVUID = (access & Opcodes.ACC_ENUM) == 0;
if (computeSVUID) { if (computeSVUID) {
this.name = name; this.name = name;
@ -396,6 +396,11 @@ public class SerialVersionUIDAdder extends ClassVisitor {
/* /*
* 2. The class modifiers written as a 32-bit integer. * 2. The class modifiers written as a 32-bit integer.
*/ */
int access = this.access;
if ((access & Opcodes.ACC_INTERFACE) != 0) {
access = (svuidMethods.size() > 0) ? (access | Opcodes.ACC_ABSTRACT)
: (access & ~Opcodes.ACC_ABSTRACT);
}
dos.writeInt(access dos.writeInt(access
& (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL & (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL
| Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT)); | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT));

@ -0,0 +1,188 @@
/*
* 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.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package jdk.internal.org.objectweb.asm.commons;
import java.util.Stack;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.signature.SignatureVisitor;
/**
* A {@link SignatureVisitor} adapter for type mapping.
*
* @author Eugene Kuleshov
*/
public class SignatureRemapper extends SignatureVisitor {
private final SignatureVisitor v;
private final Remapper remapper;
private Stack<String> classNames = new Stack<String>();
public SignatureRemapper(final SignatureVisitor v, final Remapper remapper) {
this(Opcodes.ASM5, v, remapper);
}
protected SignatureRemapper(final int api, final SignatureVisitor v,
final Remapper remapper) {
super(api);
this.v = v;
this.remapper = remapper;
}
@Override
public void visitClassType(String name) {
classNames.push(name);
v.visitClassType(remapper.mapType(name));
}
@Override
public void visitInnerClassType(String name) {
String outerClassName = classNames.pop();
String className = outerClassName + '$' + name;
classNames.push(className);
String remappedOuter = remapper.mapType(outerClassName) + '$';
String remappedName = remapper.mapType(className);
int index = remappedName.startsWith(remappedOuter) ? remappedOuter
.length() : remappedName.lastIndexOf('$') + 1;
v.visitInnerClassType(remappedName.substring(index));
}
@Override
public void visitFormalTypeParameter(String name) {
v.visitFormalTypeParameter(name);
}
@Override
public void visitTypeVariable(String name) {
v.visitTypeVariable(name);
}
@Override
public SignatureVisitor visitArrayType() {
v.visitArrayType();
return this;
}
@Override
public void visitBaseType(char descriptor) {
v.visitBaseType(descriptor);
}
@Override
public SignatureVisitor visitClassBound() {
v.visitClassBound();
return this;
}
@Override
public SignatureVisitor visitExceptionType() {
v.visitExceptionType();
return this;
}
@Override
public SignatureVisitor visitInterface() {
v.visitInterface();
return this;
}
@Override
public SignatureVisitor visitInterfaceBound() {
v.visitInterfaceBound();
return this;
}
@Override
public SignatureVisitor visitParameterType() {
v.visitParameterType();
return this;
}
@Override
public SignatureVisitor visitReturnType() {
v.visitReturnType();
return this;
}
@Override
public SignatureVisitor visitSuperclass() {
v.visitSuperclass();
return this;
}
@Override
public void visitTypeArgument() {
v.visitTypeArgument();
}
@Override
public SignatureVisitor visitTypeArgument(char wildcard) {
v.visitTypeArgument(wildcard);
return this;
}
@Override
public void visitEnd() {
v.visitEnd();
classNames.pop();
}
}

@ -85,6 +85,12 @@ public class SimpleRemapper extends Remapper {
return s == null ? name : s; return s == null ? name : s;
} }
@Override
public String mapInvokeDynamicMethodName(String name, String desc) {
String s = map('.' + name + desc);
return s == null ? name : s;
}
@Override @Override
public String mapFieldName(String owner, String name, String desc) { public String mapFieldName(String owner, String name, String desc) {
String s = map(owner + '.' + name); String s = map(owner + '.' + name);

@ -68,7 +68,7 @@ import jdk.internal.org.objectweb.asm.Opcodes;
* <ul> * <ul>
* <li><i>ClassSignature</i> = ( <tt>visitFormalTypeParameter</tt> * <li><i>ClassSignature</i> = ( <tt>visitFormalTypeParameter</tt>
* <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* ( * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* (
* <tt>visitSuperClass</tt> <tt>visitInterface</tt>* )</li> * <tt>visitSuperclass</tt> <tt>visitInterface</tt>* )</li>
* <li><i>MethodSignature</i> = ( <tt>visitFormalTypeParameter</tt> * <li><i>MethodSignature</i> = ( <tt>visitFormalTypeParameter</tt>
* <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* ( * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* (
* <tt>visitParameterType</tt>* <tt>visitReturnType</tt> * <tt>visitParameterType</tt>* <tt>visitReturnType</tt>
@ -88,17 +88,17 @@ public abstract class SignatureVisitor {
/** /**
* Wildcard for an "extends" type argument. * Wildcard for an "extends" type argument.
*/ */
public static final char EXTENDS = '+'; public final static char EXTENDS = '+';
/** /**
* Wildcard for a "super" type argument. * Wildcard for a "super" type argument.
*/ */
public static final char SUPER = '-'; public final static char SUPER = '-';
/** /**
* Wildcard for a normal type argument. * Wildcard for a normal type argument.
*/ */
public static final char INSTANCEOF = '='; public final static char INSTANCEOF = '=';
/** /**
* The ASM API version implemented by this visitor. The value of this field * The ASM API version implemented by this visitor. The value of this field

@ -69,9 +69,9 @@ import jdk.internal.org.objectweb.asm.Opcodes;
public class SignatureWriter extends SignatureVisitor { public class SignatureWriter extends SignatureVisitor {
/** /**
* Buffer used to construct the signature. * Builder used to construct the signature.
*/ */
private final StringBuffer buf = new StringBuffer(); private final StringBuilder buf = new StringBuilder();
/** /**
* Indicates if the signature contains formal type parameters. * Indicates if the signature contains formal type parameters.

@ -205,6 +205,9 @@ public class InsnList {
/** /**
* Returns an iterator over the instructions in this list. * Returns an iterator over the instructions in this list.
* *
* @param index
* index of instruction for the iterator to start at
*
* @return an iterator over the instructions in this list. * @return an iterator over the instructions in this list.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

@ -856,7 +856,11 @@ public class ASMifier extends Printer {
buf.append("{\n").append("av0 = ").append(name) buf.append("{\n").append("av0 = ").append(name)
.append(".visitLocalVariableAnnotation("); .append(".visitLocalVariableAnnotation(");
buf.append(typeRef); buf.append(typeRef);
buf.append(", TypePath.fromString(\"").append(typePath).append("\"), "); if (typePath == null) {
buf.append(", null, ");
} else {
buf.append(", TypePath.fromString(\"").append(typePath).append("\"), ");
}
buf.append("new Label[] {"); buf.append("new Label[] {");
for (int i = 0; i < start.length; ++i) { for (int i = 0; i < start.length; ++i) {
buf.append(i == 0 ? " " : ", "); buf.append(i == 0 ? " " : ", ");
@ -934,7 +938,11 @@ public class ASMifier extends Printer {
buf.append("{\n").append("av0 = ").append(name).append(".") buf.append("{\n").append("av0 = ").append(name).append(".")
.append(method).append("("); .append(method).append("(");
buf.append(typeRef); buf.append(typeRef);
buf.append(", TypePath.fromString(\"").append(typePath).append("\"), "); if (typePath == null) {
buf.append(", null, ");
} else {
buf.append(", TypePath.fromString(\"").append(typePath).append("\"), ");
}
appendConstant(desc); appendConstant(desc);
buf.append(", ").append(visible).append(");\n"); buf.append(", ").append(visible).append(");\n");
text.add(buf.toString()); text.add(buf.toString());

@ -437,6 +437,9 @@ public class CheckMethodAdapter extends MethodVisitor {
* will not perform any data flow check (see * will not perform any data flow check (see
* {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}). * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
* *
* @param api
* the ASM API version implemented by this CheckMethodAdapter.
* Must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
* @param mv * @param mv
* the method visitor to which this adapter must delegate calls. * the method visitor to which this adapter must delegate calls.
* @param labels * @param labels

@ -74,34 +74,36 @@ import jdk.internal.org.objectweb.asm.TypePath;
* visitor chain to trace the class that is visited at a given point in this * visitor chain to trace the class that is visited at a given point in this
* chain. This may be useful for debugging purposes. * chain. This may be useful for debugging purposes.
* <p> * <p>
* The trace printed when visiting the {@code Hello} class is the following: * The trace printed when visiting the <tt>Hello</tt> class is the following:
* <p>
* <blockquote> * <blockquote>
* *
* <pre>{@code * <pre>
* // class version 49.0 (49) // access flags 0x21 public class Hello { * // class version 49.0 (49) // access flags 0x21 public class Hello {
* *
* // compiled from: Hello.java * // compiled from: Hello.java
* *
* // access flags 0x1 public <init> ()V ALOAD 0 INVOKESPECIAL * // access flags 0x1 public &lt;init&gt; ()V ALOAD 0 INVOKESPECIAL
* java/lang/Object <init> ()V RETURN MAXSTACK = 1 MAXLOCALS = 1 * java/lang/Object &lt;init&gt; ()V RETURN MAXSTACK = 1 MAXLOCALS = 1
* *
* // access flags 0x9 public static main ([Ljava/lang/String;)V GETSTATIC * // access flags 0x9 public static main ([Ljava/lang/String;)V GETSTATIC
* java/lang/System out Ljava/io/PrintStream; LDC "hello" * java/lang/System out Ljava/io/PrintStream; LDC &quot;hello&quot;
* INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V RETURN * INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V RETURN
* MAXSTACK = 2 MAXLOCALS = 1 } * MAXSTACK = 2 MAXLOCALS = 1 }
* }</pre> * </pre>
* *
* </blockquote> where {@code Hello} is defined by: * </blockquote> where <tt>Hello</tt> is defined by:
* <p>
* <blockquote> * <blockquote>
* *
* <pre>{@code * <pre>
* public class Hello { * public class Hello {
* *
* public static void main(String[] args) { * public static void main(String[] args) {
* System.out.println("hello"); * System.out.println(&quot;hello&quot;);
* } * }
* } * }
* }</pre> * </pre>
* *
* </blockquote> * </blockquote>
* *
@ -135,7 +137,7 @@ public final class TraceClassVisitor extends ClassVisitor {
* *
* @param cv * @param cv
* the {@link ClassVisitor} to which this visitor delegates * the {@link ClassVisitor} to which this visitor delegates
* calls. May be {@code null}. * calls. May be <tt>null</tt>.
* @param pw * @param pw
* the print writer to be used to print the class. * the print writer to be used to print the class.
*/ */
@ -148,7 +150,7 @@ public final class TraceClassVisitor extends ClassVisitor {
* *
* @param cv * @param cv
* the {@link ClassVisitor} to which this visitor delegates * the {@link ClassVisitor} to which this visitor delegates
* calls. May be {@code null}. * calls. May be <tt>null</tt>.
* @param p * @param p
* the object that actually converts visit events into text. * the object that actually converts visit events into text.
* @param pw * @param pw

@ -70,7 +70,7 @@ import jdk.internal.org.objectweb.asm.signature.SignatureVisitor;
*/ */
public final class TraceSignatureVisitor extends SignatureVisitor { public final class TraceSignatureVisitor extends SignatureVisitor {
private final StringBuffer declaration; private final StringBuilder declaration;
private boolean isInterface; private boolean isInterface;
@ -82,9 +82,9 @@ public final class TraceSignatureVisitor extends SignatureVisitor {
private boolean seenInterface; private boolean seenInterface;
private StringBuffer returnType; private StringBuilder returnType;
private StringBuffer exceptions; private StringBuilder exceptions;
/** /**
* Stack used to keep track of class types that have arguments. Each element * Stack used to keep track of class types that have arguments. Each element
@ -106,10 +106,10 @@ public final class TraceSignatureVisitor extends SignatureVisitor {
public TraceSignatureVisitor(final int access) { public TraceSignatureVisitor(final int access) {
super(Opcodes.ASM5); super(Opcodes.ASM5);
isInterface = (access & Opcodes.ACC_INTERFACE) != 0; isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
this.declaration = new StringBuffer(); this.declaration = new StringBuilder();
} }
private TraceSignatureVisitor(final StringBuffer buf) { private TraceSignatureVisitor(final StringBuilder buf) {
super(Opcodes.ASM5); super(Opcodes.ASM5);
this.declaration = buf; this.declaration = buf;
} }
@ -175,14 +175,14 @@ public final class TraceSignatureVisitor extends SignatureVisitor {
declaration.append('('); declaration.append('(');
} }
declaration.append(')'); declaration.append(')');
returnType = new StringBuffer(); returnType = new StringBuilder();
return new TraceSignatureVisitor(returnType); return new TraceSignatureVisitor(returnType);
} }
@Override @Override
public SignatureVisitor visitExceptionType() { public SignatureVisitor visitExceptionType() {
if (exceptions == null) { if (exceptions == null) {
exceptions = new StringBuffer(); exceptions = new StringBuilder();
} else { } else {
exceptions.append(", "); exceptions.append(", ");
} }

@ -1,12 +1,12 @@
Path: . Path: .
Working Copy Root Path: /hudson/jobs/objectweb-init/workspace/asm-svn-2014-10-15 Working Copy Root Path: /hudson/jobs/objectweb-init/workspace/asm-svn-2016-01-25
URL: file:///svnroot/asm/trunk/asm URL: file:///svnroot/asm/trunk/asm
Repository Root: file:///svnroot/asm Repository Root: file:///svnroot/asm
Repository UUID: 271bd773-ee82-43a6-9b2b-1890ed8ce7f9 Repository UUID: 271bd773-ee82-43a6-9b2b-1890ed8ce7f9
Revision: 1772 Revision: 1795
Node Kind: directory Node Kind: directory
Schedule: normal Schedule: normal
Last Changed Author: ebruneton Last Changed Author: ebruneton
Last Changed Rev: 1772 Last Changed Rev: 1795
Last Changed Date: 2014-09-06 09:13:07 +0200 (Sat, 06 Sep 2014) Last Changed Date: 2016-01-24 14:17:10 +0100 (Sun, 24 Jan 2016)

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -115,10 +115,31 @@ final class RSAClientKeyExchange extends HandshakeMessage {
byte[] encoded = null; byte[] encoded = null;
try { try {
boolean needFailover = false;
Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
boolean needFailover = !KeyUtil.isOracleJCEProvider( try {
cipher.getProvider().getName()); // Try UNWRAP_MODE mode firstly.
cipher.init(Cipher.UNWRAP_MODE, privateKey,
new TlsRsaPremasterSecretParameterSpec(
maxVersion.v, currentVersion.v),
generator);
// The provider selection can be delayed, please don't call
// any Cipher method before the call to Cipher.init().
needFailover = !KeyUtil.isOracleJCEProvider(
cipher.getProvider().getName());
} catch (InvalidKeyException | UnsupportedOperationException iue) {
if (debug != null && Debug.isOn("handshake")) {
System.out.println("The Cipher provider " +
cipher.getProvider().getName() +
" caused exception: " + iue.getMessage());
}
needFailover = true;
}
if (needFailover) { if (needFailover) {
// Use DECRYPT_MODE and dispose the previous initialization.
cipher.init(Cipher.DECRYPT_MODE, privateKey); cipher.init(Cipher.DECRYPT_MODE, privateKey);
boolean failed = false; boolean failed = false;
try { try {
@ -134,10 +155,7 @@ final class RSAClientKeyExchange extends HandshakeMessage {
maxVersion.v, currentVersion.v, maxVersion.v, currentVersion.v,
encoded, generator); encoded, generator);
} else { } else {
cipher.init(Cipher.UNWRAP_MODE, privateKey, // the cipher should have been initialized
new TlsRsaPremasterSecretParameterSpec(
maxVersion.v, currentVersion.v),
generator);
preMaster = (SecretKey)cipher.unwrap(encrypted, preMaster = (SecretKey)cipher.unwrap(encrypted,
"TlsRsaPremasterSecret", Cipher.SECRET_KEY); "TlsRsaPremasterSecret", Cipher.SECRET_KEY);
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -365,17 +365,6 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl {
/* Class and subclass dynamic debugging support */ /* Class and subclass dynamic debugging support */
private static final Debug debug = Debug.getInstance("ssl"); private static final Debug debug = Debug.getInstance("ssl");
/*
* Is it the first application record to write?
*/
private boolean isFirstAppOutputRecord = true;
/*
* If AppOutputStream needs to delay writes of small packets, we
* will use this to store the data until we actually do the write.
*/
private ByteArrayOutputStream heldRecordBuffer = null;
/* /*
* Whether local cipher suites preference in server side should be * Whether local cipher suites preference in server side should be
* honored during handshaking? * honored during handshaking?
@ -998,9 +987,21 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl {
Plaintext plainText = null; Plaintext plainText = null;
while (((state = getConnectionState()) != cs_CLOSED) && while (((state = getConnectionState()) != cs_CLOSED) &&
(state != cs_ERROR) && (state != cs_APP_CLOSED)) { (state != cs_ERROR) && (state != cs_APP_CLOSED)) {
// clean the buffer
/*
* clean the buffer and check if it is too small, e.g. because
* the AppInputStream did not have the chance to see the
* current packet length but rather something like that of the
* handshake before. In that case we return 0 at this point to
* give the caller the chance to adjust the buffer.
*/
if (buffer != null) { if (buffer != null) {
buffer.clear(); buffer.clear();
if (buffer.remaining() <
inputRecord.bytesInCompletePacket(sockInput)) {
return 0;
}
} }
/* /*

@ -1408,7 +1408,7 @@ InflateFully(jzfile *zip, jzentry *entry, void *buf, char **msg)
case Z_OK: case Z_OK:
break; break;
case Z_STREAM_END: case Z_STREAM_END:
if (count != 0 || strm.total_out != entry->size) { if (count != 0 || strm.total_out != (uInt)entry->size) {
*msg = "inflateFully: Unexpected end of stream"; *msg = "inflateFully: Unexpected end of stream";
inflateEnd(&strm); inflateEnd(&strm);
return JNI_FALSE; return JNI_FALSE;
@ -1528,7 +1528,7 @@ ZIP_InflateFully(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pm
case Z_OK: case Z_OK:
break; break;
case Z_STREAM_END: case Z_STREAM_END:
if (strm.total_out != outLen) { if (strm.total_out != (uInt)outLen) {
*pmsg = "INFLATER_inflateFully: Unexpected end of stream"; *pmsg = "INFLATER_inflateFully: Unexpected end of stream";
inflateEnd(&strm); inflateEnd(&strm);
return JNI_FALSE; return JNI_FALSE;

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,10 +23,6 @@
* questions. * questions.
*/ */
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
@ -77,21 +73,6 @@ static jfieldID backupResult_bytesTransferred;
static jfieldID backupResult_context; static jfieldID backupResult_context;
/**
* Win32 APIs not available in Windows XP
*/
typedef HANDLE (WINAPI* FindFirstStream_Proc)(LPCWSTR, STREAM_INFO_LEVELS, LPVOID, DWORD);
typedef BOOL (WINAPI* FindNextStream_Proc)(HANDLE, LPVOID);
typedef BOOLEAN (WINAPI* CreateSymbolicLinkProc) (LPCWSTR, LPCWSTR, DWORD);
typedef BOOL (WINAPI* GetFinalPathNameByHandleProc) (HANDLE, LPWSTR, DWORD, DWORD);
static FindFirstStream_Proc FindFirstStream_func;
static FindNextStream_Proc FindNextStream_func;
static CreateSymbolicLinkProc CreateSymbolicLink_func;
static GetFinalPathNameByHandleProc GetFinalPathNameByHandle_func;
static void throwWindowsException(JNIEnv* env, DWORD lastError) { static void throwWindowsException(JNIEnv* env, DWORD lastError) {
jobject x = JNU_NewObjectByName(env, "sun/nio/fs/WindowsException", jobject x = JNU_NewObjectByName(env, "sun/nio/fs/WindowsException",
"(I)V", lastError); "(I)V", lastError);
@ -108,7 +89,6 @@ JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_initIDs(JNIEnv* env, jclass this) Java_sun_nio_fs_WindowsNativeDispatcher_initIDs(JNIEnv* env, jclass this)
{ {
jclass clazz; jclass clazz;
HMODULE h;
clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$FirstFile"); clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$FirstFile");
CHECK_NULL(clazz); CHECK_NULL(clazz);
@ -175,24 +155,6 @@ Java_sun_nio_fs_WindowsNativeDispatcher_initIDs(JNIEnv* env, jclass this)
CHECK_NULL(backupResult_bytesTransferred); CHECK_NULL(backupResult_bytesTransferred);
backupResult_context = (*env)->GetFieldID(env, clazz, "context", "J"); backupResult_context = (*env)->GetFieldID(env, clazz, "context", "J");
CHECK_NULL(backupResult_context); CHECK_NULL(backupResult_context);
// get handle to kernel32
if (GetModuleHandleExW((GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT),
(LPCWSTR)&CreateFileW, &h) != 0)
{
// requires Windows Server 2003 or newer
FindFirstStream_func =
(FindFirstStream_Proc)GetProcAddress(h, "FindFirstStreamW");
FindNextStream_func =
(FindNextStream_Proc)GetProcAddress(h, "FindNextStreamW");
// requires Windows Vista or newer
CreateSymbolicLink_func =
(CreateSymbolicLinkProc)GetProcAddress(h, "CreateSymbolicLinkW");
GetFinalPathNameByHandle_func =
(GetFinalPathNameByHandleProc)GetProcAddress(h, "GetFinalPathNameByHandleW");
}
} }
JNIEXPORT jlong JNICALL JNIEXPORT jlong JNICALL
@ -404,12 +366,7 @@ Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstStream0(JNIEnv* env, jclass thi
LPCWSTR lpFileName = jlong_to_ptr(address); LPCWSTR lpFileName = jlong_to_ptr(address);
HANDLE handle; HANDLE handle;
if (FindFirstStream_func == NULL) { handle = FindFirstStreamW(lpFileName, FindStreamInfoStandard, &data, 0);
JNU_ThrowInternalError(env, "Should not get here");
return;
}
handle = (*FindFirstStream_func)(lpFileName, FindStreamInfoStandard, &data, 0);
if (handle != INVALID_HANDLE_VALUE) { if (handle != INVALID_HANDLE_VALUE) {
jstring name = (*env)->NewString(env, data.cStreamName, (jsize)wcslen(data.cStreamName)); jstring name = (*env)->NewString(env, data.cStreamName, (jsize)wcslen(data.cStreamName));
if (name == NULL) if (name == NULL)
@ -433,12 +390,7 @@ Java_sun_nio_fs_WindowsNativeDispatcher_FindNextStream(JNIEnv* env, jclass this,
WIN32_FIND_STREAM_DATA data; WIN32_FIND_STREAM_DATA data;
HANDLE h = (HANDLE)jlong_to_ptr(handle); HANDLE h = (HANDLE)jlong_to_ptr(handle);
if (FindNextStream_func == NULL) { if (FindNextStreamW(h, &data) != 0) {
JNU_ThrowInternalError(env, "Should not get here");
return NULL;
}
if ((*FindNextStream_func)(h, &data) != 0) {
return (*env)->NewString(env, data.cStreamName, (jsize)wcslen(data.cStreamName)); return (*env)->NewString(env, data.cStreamName, (jsize)wcslen(data.cStreamName));
} else { } else {
if (GetLastError() != ERROR_HANDLE_EOF) if (GetLastError() != ERROR_HANDLE_EOF)
@ -1087,13 +1039,8 @@ Java_sun_nio_fs_WindowsNativeDispatcher_CreateSymbolicLink0(JNIEnv* env,
LPCWSTR link = jlong_to_ptr(linkAddress); LPCWSTR link = jlong_to_ptr(linkAddress);
LPCWSTR target = jlong_to_ptr(targetAddress); LPCWSTR target = jlong_to_ptr(targetAddress);
if (CreateSymbolicLink_func == NULL) {
JNU_ThrowInternalError(env, "Should not get here");
return;
}
/* On Windows 64-bit this appears to succeed even when there is insufficient privileges */ /* On Windows 64-bit this appears to succeed even when there is insufficient privileges */
if ((*CreateSymbolicLink_func)(link, target, (DWORD)flags) == 0) if (CreateSymbolicLinkW(link, target, (DWORD)flags) == 0)
throwWindowsException(env, GetLastError()); throwWindowsException(env, GetLastError());
} }
@ -1155,12 +1102,7 @@ Java_sun_nio_fs_WindowsNativeDispatcher_GetFinalPathNameByHandle(JNIEnv* env,
HANDLE h = (HANDLE)jlong_to_ptr(handle); HANDLE h = (HANDLE)jlong_to_ptr(handle);
DWORD len; DWORD len;
if (GetFinalPathNameByHandle_func == NULL) { len = GetFinalPathNameByHandleW(h, path, MAX_PATH, 0);
JNU_ThrowInternalError(env, "Should not get here");
return NULL;
}
len = (*GetFinalPathNameByHandle_func)(h, path, MAX_PATH, 0);
if (len > 0) { if (len > 0) {
if (len < MAX_PATH) { if (len < MAX_PATH) {
rv = (*env)->NewString(env, (const jchar *)path, (jsize)len); rv = (*env)->NewString(env, (const jchar *)path, (jsize)len);
@ -1168,7 +1110,7 @@ Java_sun_nio_fs_WindowsNativeDispatcher_GetFinalPathNameByHandle(JNIEnv* env,
len += 1; /* return length does not include terminator */ len += 1; /* return length does not include terminator */
lpBuf = (WCHAR*)malloc(len * sizeof(WCHAR)); lpBuf = (WCHAR*)malloc(len * sizeof(WCHAR));
if (lpBuf != NULL) { if (lpBuf != NULL) {
len = (*GetFinalPathNameByHandle_func)(h, lpBuf, len, 0); len = GetFinalPathNameByHandleW(h, lpBuf, len, 0);
if (len > 0) { if (len > 0) {
rv = (*env)->NewString(env, (const jchar *)lpBuf, (jsize)len); rv = (*env)->NewString(env, (const jchar *)lpBuf, (jsize)len);
} else { } else {

@ -24,7 +24,6 @@
package java.net.http; package java.net.http;
import java.util.Locale; import java.util.Locale;
import sun.util.logging.PlatformLogger;
/** /**
* -Djava.net.HttpClient.log=errors,requests,headers,frames[:type:type2:..],content * -Djava.net.HttpClient.log=errors,requests,headers,frames[:type:type2:..],content
@ -35,9 +34,11 @@ import sun.util.logging.PlatformLogger;
* *
* Logger name is "java.net.http.HttpClient" * Logger name is "java.net.http.HttpClient"
*/ */
class Log { // implements System.Logger in order to be skipped when printing the caller's
// information
abstract class Log implements System.Logger {
final static String logProp = "java.net.http.HttpClient.log"; static final String logProp = "java.net.http.HttpClient.log";
public static final int OFF = 0; public static final int OFF = 0;
public static final int ERRORS = 0x1; public static final int ERRORS = 0x1;
@ -55,7 +56,7 @@ class Log {
public static final int ALL = CONTROL| DATA | WINDOW_UPDATES; public static final int ALL = CONTROL| DATA | WINDOW_UPDATES;
static int frametypes; static int frametypes;
static sun.util.logging.PlatformLogger logger; static final System.Logger logger;
static { static {
String s = Utils.getNetProperty(logProp); String s = Utils.getNetProperty(logProp);
@ -111,7 +112,9 @@ class Log {
} }
} }
if (logging != OFF) { if (logging != OFF) {
logger = PlatformLogger.getLogger("java.net.http.HttpClient"); logger = System.getLogger("java.net.http.HttpClient");
} else {
logger = null;
} }
} }
@ -137,34 +140,38 @@ class Log {
static void logError(String s) { static void logError(String s) {
if (errors()) if (errors())
logger.info("ERROR: " + s); logger.log(Level.INFO, "ERROR: " + s);
} }
static void logError(Throwable t) { static void logError(Throwable t) {
if (errors()) { if (errors()) {
String s = Utils.stackTrace(t); String s = Utils.stackTrace(t);
logger.info("ERROR: " + s); logger.log(Level.INFO, "ERROR: " + s);
} }
} }
static void logSSL(String s) { static void logSSL(String s) {
if (ssl()) if (ssl())
logger.info("SSL: " + s); logger.log(Level.INFO, "SSL: " + s);
} }
static void logRequest(String s) { static void logRequest(String s) {
if (requests()) if (requests())
logger.info("REQUEST: " + s); logger.log(Level.INFO, "REQUEST: " + s);
} }
static void logResponse(String s) { static void logResponse(String s) {
if (requests()) if (requests())
logger.info("RESPONSE: " + s); logger.log(Level.INFO, "RESPONSE: " + s);
} }
static void logHeaders(String s) { static void logHeaders(String s) {
if (headers()) if (headers())
logger.info("HEADERS: " + s); logger.log(Level.INFO, "HEADERS: " + s);
} }
// not instantiable
private Log() {}
// END HTTP2 // END HTTP2
} }

@ -155,9 +155,13 @@ public final class IncludeLocalesPlugin implements TransformerPlugin, ResourcePr
@Override @Override
public void configure(Map<String, String> config) { public void configure(Map<String, String> config) {
priorityList = Arrays.stream(config.get(NAME).split(",")) try {
.map(Locale.LanguageRange::new) priorityList = Arrays.stream(config.get(NAME).split(","))
.collect(Collectors.toList()); .map(Locale.LanguageRange::new)
.collect(Collectors.toList());
} catch (IllegalArgumentException iae) {
throw new PluginException(iae.getLocalizedMessage());
}
} }
@Override @Override
@ -168,7 +172,7 @@ public final class IncludeLocalesPlugin implements TransformerPlugin, ResourcePr
// jdk.localedata module validation // jdk.localedata module validation
Set<String> packages = module.getAllPackages(); Set<String> packages = module.getAllPackages();
if (!packages.containsAll(LOCALEDATA_PACKAGES)) { if (!packages.containsAll(LOCALEDATA_PACKAGES)) {
throw new PluginException("Missing locale data packages in jdk.localedata:\n\t" + throw new PluginException(PluginsResourceBundle.getMessage(NAME + ".missingpackages") +
LOCALEDATA_PACKAGES.stream() LOCALEDATA_PACKAGES.stream()
.filter(pn -> !packages.contains(pn)) .filter(pn -> !packages.contains(pn))
.collect(Collectors.joining(",\n\t"))); .collect(Collectors.joining(",\n\t")));
@ -186,6 +190,10 @@ public final class IncludeLocalesPlugin implements TransformerPlugin, ResourcePr
filtered = filterLocales(available); filtered = filterLocales(available);
if (filtered.isEmpty()) {
throw new PluginException(PluginsResourceBundle.getMessage(NAME + ".nomatchinglocales"));
}
try { try {
String value = META_FILES + filtered.stream() String value = META_FILES + filtered.stream()
.map(s -> includeLocaleFilePatterns(s)) .map(s -> includeLocaleFilePatterns(s))

@ -68,9 +68,18 @@ zip.argument=[comma separated list of resource paths]
zip.description=ZIP Compression zip.description=ZIP Compression
include-locales.argument=<langtag>[,<langtag>]* include-locales.argument=\
<langtag>[,<langtag>]*
include-locales.description=BCP 47 language tags separated by a comma, allowing locale matching\ndefined in RFC 4647. eg: en,ja,*-IN include-locales.description=\
BCP 47 language tags separated by a comma, allowing locale matching\n\
defined in RFC 4647. eg: en,ja,*-IN
include-locales.missingpackages=\
Missing locale data packages in jdk.localedata:\n\t
include-locales.nomatchinglocales=\
No matching locales found. Check the specified pattern.
main.status.ok=Functional. main.status.ok=Functional.

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -67,7 +67,7 @@ public interface RuntimeConstants {
/* Class File Constants */ /* Class File Constants */
int JAVA_MAGIC = 0xcafebabe; int JAVA_MAGIC = 0xcafebabe;
int JAVA_MIN_SUPPORTED_VERSION = 45; int JAVA_MIN_SUPPORTED_VERSION = 45;
int JAVA_MAX_SUPPORTED_VERSION = 52; int JAVA_MAX_SUPPORTED_VERSION = 53;
int JAVA_MAX_SUPPORTED_MINOR_VERSION = 0; int JAVA_MAX_SUPPORTED_MINOR_VERSION = 0;
/* Generate class file version for 1.1 by default */ /* Generate class file version for 1.1 by default */

@ -32,6 +32,7 @@ tier1 = \
-java/util/WeakHashMap/GCDuringIteration.java \ -java/util/WeakHashMap/GCDuringIteration.java \
-java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \ -java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \
-java/util/concurrent/forkjoin/FJExceptionTableLeak.java \ -java/util/concurrent/forkjoin/FJExceptionTableLeak.java \
-java/util/TimeZone/Bug6772689.java \
sun/nio/cs/ISO8859x.java \ sun/nio/cs/ISO8859x.java \
java/nio/Buffer \ java/nio/Buffer \
com/sun/crypto/provider/Cipher \ com/sun/crypto/provider/Cipher \
@ -42,6 +43,7 @@ tier2 = \
java/util/WeakHashMap/GCDuringIteration.java \ java/util/WeakHashMap/GCDuringIteration.java \
java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \ java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \
java/util/concurrent/forkjoin/FJExceptionTableLeak.java \ java/util/concurrent/forkjoin/FJExceptionTableLeak.java \
java/util/TimeZone/Bug6772689.java \
:jdk_io \ :jdk_io \
:jdk_nio \ :jdk_nio \
-sun/nio/cs/ISO8859x.java \ -sun/nio/cs/ISO8859x.java \
@ -492,7 +494,8 @@ needs_jdk = \
sun/reflect/CallerSensitive/MissingCallerSensitive.java \ sun/reflect/CallerSensitive/MissingCallerSensitive.java \
sun/security/util/Resources/NewNamesFormat.java \ sun/security/util/Resources/NewNamesFormat.java \
vm/verifier/defaultMethods/DefaultMethodRegressionTestsRun.java \ vm/verifier/defaultMethods/DefaultMethodRegressionTestsRun.java \
javax/xml/ws/clientjar/TestWsImport.java javax/xml/ws/clientjar/TestWsImport.java \
javax/xml/bind/xjc/8145039/JaxbMarshallTest.java
# JRE adds further tests to compact3 # JRE adds further tests to compact3
# #

@ -0,0 +1,46 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import jdk.testlibrary.OutputAnalyzer;
import jdk.testlibrary.ProcessTools;
import jdk.testlibrary.Utils;
/* @test
* @bug 8147456
* @summary Check that providing a non-existing -agentpath gives a proper error.
* @author Sharath Ballal
*
* @library /lib/testlibrary
* @modules java.management
* @build jdk.testlibrary.*
* @build BadAgentPath
* @run driver BadAgentPath
*/
public class BadAgentPath {
public static void main(String[] args) throws Throwable {
OutputAnalyzer output = ProcessTools.executeTestJvm("-agentpath:/badAgent/agent", "-version");
output.shouldContain("Could not find agent library /badAgent/agent");
}
}

@ -0,0 +1,80 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.
*/
/* @test
* @compile TestAccessClass.java TestCls.java
* @run testng/othervm -ea -esa test.java.lang.invoke.t8150782.TestAccessClass
*/
package test.java.lang.invoke.t8150782;
import java.lang.invoke.*;
import static java.lang.invoke.MethodHandles.*;
import static org.testng.AssertJUnit.*;
import org.testng.annotations.*;
public class TestAccessClass {
private static boolean initializedClass1;
private static class Class1 {
static {
initializedClass1 = true;
}
}
@Test
public void initializerNotRun() throws IllegalAccessException {
lookup().accessClass(Class1.class);
assertFalse(initializedClass1);
}
@Test
public void returnsSameClass() throws IllegalAccessException, ClassNotFoundException {
Class<?> aClass = lookup().accessClass(Class1.class);
assertEquals(Class1.class, aClass);
}
@DataProvider
Object[][] illegalAccessAccess() {
return new Object[][] {
{publicLookup(), Class1.class},
{publicLookup(), TestCls.getPrivateSIC()}
};
}
@Test(dataProvider = "illegalAccessAccess", expectedExceptions = {IllegalAccessException.class})
public void illegalAccessExceptionTest(Lookup lookup, Class<?> klass) throws IllegalAccessException, ClassNotFoundException {
lookup.accessClass(klass);
}
@Test
public void okAccess() throws IllegalAccessException {
lookup().accessClass(TestCls.getPrivateSIC());
}
}

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,9 +22,17 @@
* or visit www.oracle.com if you need additional information or have any * or visit www.oracle.com if you need additional information or have any
* questions. * questions.
*/ */
package test.java.lang.invoke.t8150782;
import static java.lang.invoke.MethodHandles.*;
public class TestCls {
public static final Lookup LOOKUP = lookup();
private static class PrivateSIC {}
public static Class getPrivateSIC() { return PrivateSIC.class; }
public static Lookup getLookupForPrivateSIC() { return lookup(); }
module jdk.deploy.osx {
requires java.desktop;
requires java.scripting;
} }

@ -0,0 +1,90 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.
*/
/* @test
* @compile TestFindClass.java TestCls.java
* @run testng/othervm -ea -esa test.java.lang.invoke.t8150782.TestFindClass
*/
package test.java.lang.invoke.t8150782;
import java.lang.invoke.*;
import static java.lang.invoke.MethodHandles.*;
import static org.testng.AssertJUnit.*;
import org.testng.annotations.*;
public class TestFindClass {
private static final String PACKAGE_PREFIX = "test.java.lang.invoke.t8150782.";
private static boolean initializedClass1;
private static class Class1 {
static {
initializedClass1 = true;
}
}
@Test
public void initializerNotRun() throws IllegalAccessException, ClassNotFoundException {
lookup().findClass(PACKAGE_PREFIX + "TestFindClass$Class1");
assertFalse(initializedClass1);
}
@Test
public void returnsRequestedClass() throws IllegalAccessException, ClassNotFoundException {
Class<?> aClass = lookup().findClass(PACKAGE_PREFIX + "TestFindClass$Class1");
assertEquals(Class1.class, aClass);
}
@Test(expectedExceptions = {ClassNotFoundException.class})
public void classNotFoundExceptionTest() throws IllegalAccessException, ClassNotFoundException {
lookup().findClass(PACKAGE_PREFIX + "TestFindClass$NonExistent");
}
@DataProvider
Object[][] illegalAccessFind() {
return new Object[][] {
{publicLookup(), PACKAGE_PREFIX + "TestFindClass$Class1"},
{publicLookup(), PACKAGE_PREFIX + "TestCls$PrivateSIC"}
};
}
/**
* Assertion: @throws IllegalAccessException if the class is not accessible, using the allowed access modes.
*/
@Test(dataProvider = "illegalAccessFind", expectedExceptions = {ClassNotFoundException.class})
public void illegalAccessExceptionTest(Lookup lookup, String className) throws IllegalAccessException, ClassNotFoundException {
lookup.findClass(className);
}
@Test
public void okAccess() throws IllegalAccessException, ClassNotFoundException {
lookup().findClass(PACKAGE_PREFIX + "TestCls$PrivateSIC");
}
}

@ -0,0 +1,70 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.
*/
/* @test
* @compile TestLookup.java TestCls.java
* @run testng/othervm -ea -esa test.java.lang.invoke.t8150782.TestLookup
*/
package test.java.lang.invoke.t8150782;
import org.testng.annotations.Test;
import static java.lang.invoke.MethodHandles.*;
import static org.testng.AssertJUnit.*;
public class TestLookup {
@Test
public void testClassLoaderChange() {
Lookup lookup = lookup();
assertNotNull(lookup.lookupClass().getClassLoader());
Lookup lookup2 = lookup.in(Object.class);
assertNull(lookup2.lookupClass().getClassLoader());
}
@Test(expectedExceptions = {ClassNotFoundException.class})
public void testPublicCannotLoadUserClass() throws IllegalAccessException, ClassNotFoundException {
Lookup lookup = publicLookup();
lookup.findClass("test.java.lang.invoke.t8150782.TestCls");
}
@Test
public void testPublicCanLoadSystemClass() throws IllegalAccessException, ClassNotFoundException {
Lookup lookup = publicLookup();
lookup.findClass("java.util.HashMap");
}
@Test
public void testPublicInChangesClassLoader() {
Lookup lookup = publicLookup();
// Temporarily exclude until 8148697 is resolved, specifically:
// "publicLookup changed so that the lookup class is in an unnamed module"
//assertNull(lookup.lookupClass().getClassLoader());
Lookup lookup2 = lookup.in(TestCls.class);
assertNotNull(lookup2.lookupClass().getClassLoader());
}
}

@ -24,7 +24,7 @@
/** /**
* @test * @test
* @build ModuleSetAccessibleTest * @build ModuleSetAccessibleTest
* @modules java.base/sun.misc * @modules java.base/jdk.internal.misc
* @run testng ModuleSetAccessibleTest * @run testng ModuleSetAccessibleTest
* @summary Test java.lang.reflect.AccessibleObject with modules * @summary Test java.lang.reflect.AccessibleObject with modules
*/ */
@ -38,7 +38,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Module; import java.lang.reflect.Module;
import sun.misc.Unsafe; import jdk.internal.misc.Unsafe;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import static org.testng.Assert.*; import static org.testng.Assert.*;

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,6 +23,7 @@
/* @test /* @test
* @bug 4460583 4470470 4840199 6419424 6710579 6596323 6824135 6395224 7142919 * @bug 4460583 4470470 4840199 6419424 6710579 6596323 6824135 6395224 7142919
* 8151582
* @run main/othervm AsyncCloseAndInterrupt * @run main/othervm AsyncCloseAndInterrupt
* @summary Comprehensive test of asynchronous closing and interruption * @summary Comprehensive test of asynchronous closing and interruption
* @author Mark Reinhold * @author Mark Reinhold
@ -89,7 +90,7 @@ public class AsyncCloseAndInterrupt {
private static void initRefuser() throws IOException { private static void initRefuser() throws IOException {
refuser = ServerSocketChannel.open(); refuser = ServerSocketChannel.open();
refuser.socket().bind(wildcardAddress); refuser.bind(wildcardAddress, 1); // use minimum backlog
} }
// Dead pipe source and sink // Dead pipe source and sink
@ -349,7 +350,7 @@ public class AsyncCloseAndInterrupt {
static final Op CONNECT = new Op("connect") { static final Op CONNECT = new Op("connect") {
void setup() { void setup() {
waitPump("connect wait for pumping refuser ..."); waitPump("connect waiting for pumping refuser ...");
} }
void doIO(InterruptibleChannel ich) throws IOException { void doIO(InterruptibleChannel ich) throws IOException {
SocketChannel sc = (SocketChannel)ich; SocketChannel sc = (SocketChannel)ich;
@ -361,7 +362,7 @@ public class AsyncCloseAndInterrupt {
static final Op FINISH_CONNECT = new Op("finishConnect") { static final Op FINISH_CONNECT = new Op("finishConnect") {
void setup() { void setup() {
waitPump("finishConnect wait for pumping refuser ..."); waitPump("finishConnect waiting for pumping refuser ...");
} }
void doIO(InterruptibleChannel ich) throws IOException { void doIO(InterruptibleChannel ich) throws IOException {
SocketChannel sc = (SocketChannel)ich; SocketChannel sc = (SocketChannel)ich;
@ -498,12 +499,11 @@ public class AsyncCloseAndInterrupt {
private static volatile boolean pumpReady = false; private static volatile boolean pumpReady = false;
private static void waitPump(String msg){ private static void waitPump(String msg){
pumpReady = false;
log.println(msg); log.println(msg);
while (!pumpReady){ while (!pumpReady){
sleep(200); sleep(200);
} }
log.println(msg + " done");
} }
// Create a pump thread dedicated to saturate refuser's connection backlog // Create a pump thread dedicated to saturate refuser's connection backlog
@ -520,28 +520,34 @@ public class AsyncCloseAndInterrupt {
// Saturate the refuser's connection backlog so that further connection // Saturate the refuser's connection backlog so that further connection
// attempts will be blocked // attempts will be blocked
pumpReady = false;
while (!pumpDone) { while (!pumpDone) {
SocketChannel sc = SocketChannel.open(); SocketChannel sc = SocketChannel.open();
sc.configureBlocking(false); sc.configureBlocking(false);
boolean connected = sc.connect(refuser.socket().getLocalSocketAddress()); boolean connected = sc.connect(refuser.socket().getLocalSocketAddress());
// Assume that the connection backlog is saturated if a // Assume that the connection backlog is saturated if a
// client cannot connect to the refuser within 50 miliseconds // client cannot connect to the refuser within 50 milliseconds
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
while (!connected && (System.currentTimeMillis() - start < 50)) { while (!pumpReady && !connected
&& (System.currentTimeMillis() - start < 50)) {
connected = sc.finishConnect(); connected = sc.finishConnect();
} }
if (connected) { if (connected) {
// Retain so that finalizer doesn't close // Retain so that finalizer doesn't close
refuserClients.add(sc); refuserClients.add(sc);
pumpReady = false;
} else { } else {
sc.close(); sc.close();
pumpReady = true; pumpReady = true;
} }
} }
for (SocketChannel sc : refuserClients) {
sc.close();
}
refuser.close();
log.println("Stop pumping refuser ..."); log.println("Stop pumping refuser ...");
return refuserClients.size(); return refuserClients.size();
} }
@ -565,8 +571,6 @@ public class AsyncCloseAndInterrupt {
sleep(50); sleep(50);
} while (!t.ready); } while (!t.ready);
sleep(100);
switch (test) { switch (test) {
case TEST_INTR: case TEST_INTR:

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,6 +23,7 @@
/* @test /* @test
* @bug 7200742 * @bug 7200742
* @key intermittent
* @summary Test that Selector doesn't spin when changing interest ops * @summary Test that Selector doesn't spin when changing interest ops
*/ */

@ -761,6 +761,7 @@ public class TCKZonedDateTime extends AbstractDateTimeTest {
{"2012-06-30T12:30:40-01:00[UT-01:00]", 2012, 6, 30, 12, 30, 40, 0, "UT-01:00"}, {"2012-06-30T12:30:40-01:00[UT-01:00]", 2012, 6, 30, 12, 30, 40, 0, "UT-01:00"},
{"2012-06-30T12:30:40-01:00[UTC-01:00]", 2012, 6, 30, 12, 30, 40, 0, "UTC-01:00"}, {"2012-06-30T12:30:40-01:00[UTC-01:00]", 2012, 6, 30, 12, 30, 40, 0, "UTC-01:00"},
{"2012-06-30T12:30:40+01:00[Europe/London]", 2012, 6, 30, 12, 30, 40, 0, "Europe/London"}, {"2012-06-30T12:30:40+01:00[Europe/London]", 2012, 6, 30, 12, 30, 40, 0, "Europe/London"},
{"2012-06-30T12:30:40+01", 2012, 6, 30, 12, 30, 40, 0, "+01:00"},
}; };
} }

@ -59,11 +59,13 @@
*/ */
package tck.java.time.format; package tck.java.time.format;
import static java.time.format.DateTimeFormatter.BASIC_ISO_DATE;
import static java.time.temporal.ChronoField.DAY_OF_MONTH; import static java.time.temporal.ChronoField.DAY_OF_MONTH;
import static java.time.temporal.ChronoField.HOUR_OF_DAY; import static java.time.temporal.ChronoField.HOUR_OF_DAY;
import static java.time.temporal.ChronoField.MINUTE_OF_HOUR; import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
import static java.time.temporal.ChronoField.MONTH_OF_YEAR; import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
import static java.time.temporal.ChronoField.NANO_OF_SECOND; import static java.time.temporal.ChronoField.NANO_OF_SECOND;
import static java.time.temporal.ChronoField.OFFSET_SECONDS;
import static java.time.temporal.ChronoField.YEAR; import static java.time.temporal.ChronoField.YEAR;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
@ -73,6 +75,7 @@ import java.time.YearMonth;
import java.time.ZoneOffset; import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder; import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.format.SignStyle; import java.time.format.SignStyle;
import java.time.format.TextStyle; import java.time.format.TextStyle;
import java.time.temporal.Temporal; import java.time.temporal.Temporal;
@ -339,6 +342,18 @@ public class TCKDateTimeFormatterBuilder {
{"+HH", 2, 0, 45, "+02"}, {"+HH", 2, 0, 45, "+02"},
{"+HH", 2, 30, 45, "+02"}, {"+HH", 2, 30, 45, "+02"},
{"+HHmm", 2, 0, 0, "+02"},
{"+HHmm", -2, 0, 0, "-02"},
{"+HHmm", 2, 30, 0, "+0230"},
{"+HHmm", 2, 0, 45, "+02"},
{"+HHmm", 2, 30, 45, "+0230"},
{"+HH:mm", 2, 0, 0, "+02"},
{"+HH:mm", -2, 0, 0, "-02"},
{"+HH:mm", 2, 30, 0, "+02:30"},
{"+HH:mm", 2, 0, 45, "+02"},
{"+HH:mm", 2, 30, 45, "+02:30"},
{"+HHMM", 2, 0, 0, "+0200"}, {"+HHMM", 2, 0, 0, "+0200"},
{"+HHMM", -2, 0, 0, "-0200"}, {"+HHMM", -2, 0, 0, "-0200"},
{"+HHMM", 2, 30, 0, "+0230"}, {"+HHMM", 2, 30, 0, "+0230"},
@ -374,6 +389,20 @@ public class TCKDateTimeFormatterBuilder {
{"+HH:MM:SS", 2, 30, 0, "+02:30:00"}, {"+HH:MM:SS", 2, 30, 0, "+02:30:00"},
{"+HH:MM:SS", 2, 0, 45, "+02:00:45"}, {"+HH:MM:SS", 2, 0, 45, "+02:00:45"},
{"+HH:MM:SS", 2, 30, 45, "+02:30:45"}, {"+HH:MM:SS", 2, 30, 45, "+02:30:45"},
{"+HHmmss", 2, 0, 0, "+02"},
{"+HHmmss", -2, 0, 0, "-02"},
{"+HHmmss", 2, 30, 0, "+0230"},
{"+HHmmss", 2, 0, 45, "+020045"},
{"+HHmmss", 2, 30, 45, "+023045"},
{"+HH:mm:ss", 2, 0, 0, "+02"},
{"+HH:mm:ss", -2, 0, 0, "-02"},
{"+HH:mm:ss", 2, 30, 0, "+02:30"},
{"+HH:mm:ss", 2, 0, 45, "+02:00:45"},
{"+HH:mm:ss", 2, 30, 45, "+02:30:45"},
}; };
} }
@ -878,4 +907,82 @@ public class TCKDateTimeFormatterBuilder {
assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L);
} }
@DataProvider(name="lenientOffsetParseData")
Object[][] data_lenient_offset_parse() {
return new Object[][] {
{"+HH", "+01", 3600},
{"+HH", "+0101", 3660},
{"+HH", "+010101", 3661},
{"+HH", "+01", 3600},
{"+HH", "+01:01", 3660},
{"+HH", "+01:01:01", 3661},
{"+HHmm", "+01", 3600},
{"+HHmm", "+0101", 3660},
{"+HHmm", "+010101", 3661},
{"+HH:mm", "+01", 3600},
{"+HH:mm", "+01:01", 3660},
{"+HH:mm", "+01:01:01", 3661},
{"+HHMM", "+01", 3600},
{"+HHMM", "+0101", 3660},
{"+HHMM", "+010101", 3661},
{"+HH:MM", "+01", 3600},
{"+HH:MM", "+01:01", 3660},
{"+HH:MM", "+01:01:01", 3661},
{"+HHMMss", "+01", 3600},
{"+HHMMss", "+0101", 3660},
{"+HHMMss", "+010101", 3661},
{"+HH:MM:ss", "+01", 3600},
{"+HH:MM:ss", "+01:01", 3660},
{"+HH:MM:ss", "+01:01:01", 3661},
{"+HHMMSS", "+01", 3600},
{"+HHMMSS", "+0101", 3660},
{"+HHMMSS", "+010101", 3661},
{"+HH:MM:SS", "+01", 3600},
{"+HH:MM:SS", "+01:01", 3660},
{"+HH:MM:SS", "+01:01:01", 3661},
{"+HHmmss", "+01", 3600},
{"+HHmmss", "+0101", 3660},
{"+HHmmss", "+010101", 3661},
{"+HH:mm:ss", "+01", 3600},
{"+HH:mm:ss", "+01:01", 3660},
{"+HH:mm:ss", "+01:01:01", 3661},
};
}
@Test(dataProvider="lenientOffsetParseData")
public void test_lenient_offset_parse_1(String pattern, String offset, int offsetSeconds) {
assertEquals(new DateTimeFormatterBuilder().parseLenient().appendOffset(pattern, "Z").toFormatter().parse(offset).get(OFFSET_SECONDS),
offsetSeconds);
}
@Test
public void test_lenient_offset_parse_2() {
assertEquals(new DateTimeFormatterBuilder().parseLenient().appendOffsetId().toFormatter().parse("+01").get(OFFSET_SECONDS),
3600);
}
@Test(expectedExceptions=DateTimeParseException.class)
public void test_strict_appendOffsetId() {
assertEquals(new DateTimeFormatterBuilder().appendOffsetId().toFormatter().parse("+01").get(OFFSET_SECONDS),
3600);
}
@Test(expectedExceptions=DateTimeParseException.class)
public void test_strict_appendOffset_1() {
assertEquals(new DateTimeFormatterBuilder().appendOffset("+HH:MM:ss", "Z").toFormatter().parse("+01").get(OFFSET_SECONDS),
3600);
}
@Test(expectedExceptions=DateTimeParseException.class)
public void test_strict_appendOffset_2() {
assertEquals(new DateTimeFormatterBuilder().appendOffset("+HHMMss", "Z").toFormatter().parse("+01").get(OFFSET_SECONDS),
3600);
}
@Test
public void test_basic_iso_date() {
assertEquals(BASIC_ISO_DATE.parse("20021231+01").get(OFFSET_SECONDS), 3600);
assertEquals(BASIC_ISO_DATE.parse("20021231+0101").get(OFFSET_SECONDS), 3660);
}
} }

@ -199,6 +199,30 @@ public class TCKOffsetPrinterParser {
{"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-00:23:00"}, {"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-00:23:00"},
{"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-01:23:45"}, {"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-01:23:45"},
{"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00:00:45"}, {"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00:00:45"},
{"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
{"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+01"},
{"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+01:23"},
{"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+00:23"},
{"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+01:23:45"},
{"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00:00:45"},
{"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-01"},
{"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-01:23"},
{"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-00:23"},
{"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-01:23:45"},
{"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00:00:45"},
{"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
{"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+01"},
{"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+0123"},
{"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+0023"},
{"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+012345"},
{"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "+000045"},
{"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-01"},
{"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-0123"},
{"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-0023"},
{"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-012345"},
{"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-000045"},
}; };
} }

@ -79,19 +79,24 @@ import java.time.YearMonth;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.ZoneOffset; import java.time.ZoneOffset;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.chrono.Chronology;
import java.time.chrono.ThaiBuddhistChronology; import java.time.chrono.ThaiBuddhistChronology;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder; import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DecimalStyle; import java.time.format.DecimalStyle;
import java.time.format.SignStyle; import java.time.format.SignStyle;
import java.time.format.TextStyle;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalAccessor;
import java.util.Locale; import java.util.Locale;
import java.util.function.Function; import java.util.function.Function;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test; import org.testng.annotations.Test;
/** /**
* Test DateTimeFormatter. * Test DateTimeFormatter.
* @bug 8085887
*/ */
@Test @Test
public class TestDateTimeFormatter { public class TestDateTimeFormatter {
@ -196,4 +201,75 @@ public class TestDateTimeFormatter {
assertTrue(msg.contains("11:30:56"), msg); assertTrue(msg.contains("11:30:56"), msg);
} }
@DataProvider(name="nozone_exception_cases")
Object[][] exceptionCases() {
return new Object[][] {
{LocalDateTime.of(2000, 1, 1, 1, 1), "z", "ZoneId"},
{OffsetDateTime.of(2000, 1, 1, 3, 3, 3, 0, ZoneOffset.ofTotalSeconds(60)), "z", "ZoneId"},
};
}
// Test cases that should throw an exception with a cogent message
// containing the Type being queried and the Temporal being queried.
@Test(dataProvider="nozone_exception_cases")
public void test_throws_message(Temporal temporal, String pattern, String queryName) {
DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern);
try {
fmt.format(temporal);
fail("Format using \"" + pattern + "\" with " +
temporal + " should have failed");
} catch (DateTimeException dte) {
String msg = dte.getMessage();
// Verify message contains the type that is missing and the temporal value
assertTrue(msg.contains(queryName),
String.format("\"%s\" missing from %s", queryName, msg));
String s = temporal.toString();
assertTrue(msg.contains(s),
String.format("\"%s\" missing from %s", s, msg));
}
}
// Test cases that should throw an exception with a cogent message when missing the Chronology
@Test
public void test_throws_message_chrono() {
Chronology chrono = ThaiBuddhistChronology.INSTANCE;
DateTimeFormatter fmt = new DateTimeFormatterBuilder().appendZoneId().toFormatter()
.withChronology(chrono);
LocalTime now = LocalTime.now();
try {
fmt.format(now);
fail("Format using appendZoneId() should have failed");
} catch (DateTimeException dte) {
String msg = dte.getMessage();
// Verify message contains the type that is missing and the temporal value
assertTrue(msg.contains("ZoneId"),
String.format("\"%s\" missing from %s", "ZoneId", msg));
assertTrue(msg.contains(chrono.toString()),
String.format("\"%s\" missing from %s", chrono.toString(), msg));
}
}
// Test cases that should throw an exception with a cogent message when missing the ZoneId
@Test
public void test_throws_message_zone() {
ZoneId zone = ZoneId.of("Pacific/Honolulu");
DateTimeFormatter fmt = new DateTimeFormatterBuilder().appendChronologyId().toFormatter()
.withZone(zone);
LocalTime now = LocalTime.now();
try {
fmt.format(now);
fail("Format using appendChronologyId() should have failed");
} catch (DateTimeException dte) {
String msg = dte.getMessage();
// Verify message contains the type that is missing and the temporal value
assertTrue(msg.contains("Chronology"),
String.format("\"%s\" missing from %s", "Chronology", msg));
assertTrue(msg.contains(zone.toString()),
String.format("\"%s\" missing from %s", zone.toString(), msg));
}
}
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -52,6 +52,7 @@ import static org.testng.Assert.*;
/** /**
* @test * @test
* @bug 8148748
* @summary Spliterator last-binding and fail-fast tests * @summary Spliterator last-binding and fail-fast tests
* @run testng SpliteratorLateBindingFailFastTest * @run testng SpliteratorLateBindingFailFastTest
*/ */
@ -120,8 +121,8 @@ public class SpliteratorLateBindingFailFastTest {
} }
void addList(Function<Collection<T>, ? extends List<T>> l) { void addList(Function<Collection<T>, ? extends List<T>> l) {
// @@@ If collection is instance of List then add sub-list tests
addCollection(l); addCollection(l);
addCollection(l.andThen(list -> list.subList(0, list.size())));
} }
void addMap(Function<Map<T, T>, ? extends Map<T, T>> mapConstructor) { void addMap(Function<Map<T, T>, ? extends Map<T, T>> mapConstructor) {

@ -24,6 +24,7 @@
/* /*
* @test * @test
* @bug 6772689 * @bug 6772689
* @key intermittent
* @summary Test for standard-to-daylight transitions at midnight: * @summary Test for standard-to-daylight transitions at midnight:
* date stays on the given day. * date stays on the given day.
*/ */

@ -101,9 +101,6 @@ public class SSLSocketSSLEngineTemplate {
private static final boolean debug = false; private static final boolean debug = false;
private final SSLContext sslc; private final SSLContext sslc;
private SSLEngine serverEngine; // server-side SSLEngine private SSLEngine serverEngine; // server-side SSLEngine
private SSLSocket sslSocket; // client-side socket
private ServerSocket serverSocket; // server-side Socket, generates the...
private Socket socket; // server-side socket that will read
private final byte[] serverMsg = private final byte[] serverMsg =
"Hi there Client, I'm a Server.".getBytes(); "Hi there Client, I'm a Server.".getBytes();
@ -217,132 +214,128 @@ public class SSLSocketSSLEngineTemplate {
private void runTest(boolean direct) throws Exception { private void runTest(boolean direct) throws Exception {
boolean serverClose = direct; boolean serverClose = direct;
serverSocket = new ServerSocket(); // generates the server-side Socket
serverSocket.setReuseAddress(false); try (ServerSocket serverSocket = new ServerSocket()) {
serverSocket.bind(null); serverSocket.setReuseAddress(false);
int port = serverSocket.getLocalPort(); serverSocket.bind(null);
Thread thread = createClientThread(port, serverClose); int port = serverSocket.getLocalPort();
Thread thread = createClientThread(port, serverClose);
socket = serverSocket.accept(); createSSLEngine();
socket.setSoTimeout(500); createBuffers(direct);
serverSocket.close();
createSSLEngine(); // server-side socket that will read
createBuffers(direct); try (Socket socket = serverSocket.accept()) {
socket.setSoTimeout(500);
try { boolean closed = false;
boolean closed = false; // will try to read one more time in case client message
// will try to read one more time in case client message // is fragmented to multiple pieces
// is fragmented to multiple pieces boolean retry = true;
boolean retry = true;
InputStream is = socket.getInputStream(); InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream(); OutputStream os = socket.getOutputStream();
SSLEngineResult serverResult; // results from last operation SSLEngineResult serverResult; // results from last operation
/* /*
* Examining the SSLEngineResults could be much more involved, * Examining the SSLEngineResults could be much more involved,
* and may alter the overall flow of the application. * and may alter the overall flow of the application.
* *
* For example, if we received a BUFFER_OVERFLOW when trying * For example, if we received a BUFFER_OVERFLOW when trying
* to write to the output pipe, we could reallocate a larger * to write to the output pipe, we could reallocate a larger
* pipe, but instead we wait for the peer to drain it. * pipe, but instead we wait for the peer to drain it.
*/ */
byte[] inbound = new byte[8192]; byte[] inbound = new byte[8192];
byte[] outbound = new byte[8192]; byte[] outbound = new byte[8192];
while (!isEngineClosed(serverEngine)) { while (!isEngineClosed(serverEngine)) {
int len; int len;
// Inbound data // Inbound data
log("================"); log("================");
// Read from the Client side. // Read from the Client side.
try { try {
len = is.read(inbound); len = is.read(inbound);
if (len == -1) { if (len == -1) {
throw new Exception("Unexpected EOF"); throw new Exception("Unexpected EOF");
}
cTOs.put(inbound, 0, len);
} catch (SocketTimeoutException ste) {
// swallow. Nothing yet, probably waiting on us.
}
cTOs.flip();
serverResult = serverEngine.unwrap(cTOs, serverIn);
log("server unwrap: ", serverResult);
runDelegatedTasks(serverResult, serverEngine);
cTOs.compact();
// Outbound data
log("----");
serverResult = serverEngine.wrap(serverOut, sTOc);
log("server wrap: ", serverResult);
runDelegatedTasks(serverResult, serverEngine);
sTOc.flip();
if ((len = sTOc.remaining()) != 0) {
sTOc.get(outbound, 0, len);
os.write(outbound, 0, len);
// Give the other side a chance to process
}
sTOc.compact();
if (!closed && (serverOut.remaining() == 0)) {
closed = true;
/*
* We'll alternate initiatating the shutdown.
* When the server initiates, it will take one more
* loop, but tests the orderly shutdown.
*/
if (serverClose) {
serverEngine.closeOutbound();
}
serverIn.flip();
/*
* A sanity check to ensure we got what was sent.
*/
if (serverIn.remaining() != clientMsg.length) {
if (retry && serverIn.remaining() < clientMsg.length) {
log("Need to read more from client");
retry = false;
continue;
} else {
throw new Exception("Client: Data length error");
} }
cTOs.put(inbound, 0, len);
} catch (SocketTimeoutException ste) {
// swallow. Nothing yet, probably waiting on us.
} }
for (int i = 0; i < clientMsg.length; i++) { cTOs.flip();
if (clientMsg[i] != serverIn.get()) {
throw new Exception("Client: Data content error"); serverResult = serverEngine.unwrap(cTOs, serverIn);
} log("server unwrap: ", serverResult);
runDelegatedTasks(serverResult, serverEngine);
cTOs.compact();
// Outbound data
log("----");
serverResult = serverEngine.wrap(serverOut, sTOc);
log("server wrap: ", serverResult);
runDelegatedTasks(serverResult, serverEngine);
sTOc.flip();
if ((len = sTOc.remaining()) != 0) {
sTOc.get(outbound, 0, len);
os.write(outbound, 0, len);
// Give the other side a chance to process
} }
serverIn.compact();
sTOc.compact();
if (!closed && (serverOut.remaining() == 0)) {
closed = true;
/*
* We'll alternate initiatating the shutdown.
* When the server initiates, it will take one more
* loop, but tests the orderly shutdown.
*/
if (serverClose) {
serverEngine.closeOutbound();
}
serverIn.flip();
/*
* A sanity check to ensure we got what was sent.
*/
if (serverIn.remaining() != clientMsg.length) {
if (retry &&
serverIn.remaining() < clientMsg.length) {
log("Need to read more from client");
retry = false;
continue;
} else {
throw new Exception(
"Client: Data length error");
}
}
for (int i = 0; i < clientMsg.length; i++) {
if (clientMsg[i] != serverIn.get()) {
throw new Exception(
"Client: Data content error");
}
}
serverIn.compact();
}
}
} catch (Exception e) {
serverException = e;
} finally {
// Wait for the client to join up with us.
if (thread != null) {
thread.join();
} }
} }
} catch (Exception e) {
serverException = e;
} finally { } finally {
if (socket != null) {
socket.close();
}
// Wait for the client to join up with us.
if (thread != null) {
thread.join();
}
if (sslSocket != null) {
sslSocket.close();
}
if (serverException != null) { if (serverException != null) {
if (clientException != null) { if (clientException != null) {
serverException.initCause(clientException); serverException.initCause(clientException);
@ -369,11 +362,9 @@ public class SSLSocketSSLEngineTemplate {
@Override @Override
public void run() { public void run() {
try { // client-side socket
Thread.sleep(1000); // Give server time to finish setup. try (SSLSocket sslSocket = (SSLSocket)sslc.getSocketFactory().
createSocket("localhost", port)) {
sslSocket = (SSLSocket) sslc.getSocketFactory().
createSocket("localhost", port);
OutputStream os = sslSocket.getOutputStream(); OutputStream os = sslSocket.getOutputStream();
InputStream is = sslSocket.getInputStream(); InputStream is = sslSocket.getInputStream();

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -85,26 +85,26 @@ public class SSLSocketTemplate {
*/ */
void doServerSide() throws Exception { void doServerSide() throws Exception {
SSLServerSocketFactory sslssf = SSLServerSocketFactory sslssf =
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
SSLServerSocket sslServerSocket = try (SSLServerSocket sslServerSocket =
(SSLServerSocket) sslssf.createServerSocket(serverPort); (SSLServerSocket)sslssf.createServerSocket(serverPort)) {
serverPort = sslServerSocket.getLocalPort(); serverPort = sslServerSocket.getLocalPort();
/* /*
* Signal Client, we're ready for his connect. * Signal Client, we're ready for his connect.
*/ */
serverReady = true; serverReady = true;
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) {
InputStream sslIS = sslSocket.getInputStream(); InputStream sslIS = sslSocket.getInputStream();
OutputStream sslOS = sslSocket.getOutputStream(); OutputStream sslOS = sslSocket.getOutputStream();
sslIS.read(); sslIS.read();
sslOS.write(85); sslOS.write(85);
sslOS.flush(); sslOS.flush();
}
sslSocket.close(); }
} }
/* /*
@ -123,18 +123,17 @@ public class SSLSocketTemplate {
} }
SSLSocketFactory sslsf = SSLSocketFactory sslsf =
(SSLSocketFactory) SSLSocketFactory.getDefault(); (SSLSocketFactory)SSLSocketFactory.getDefault();
SSLSocket sslSocket = (SSLSocket) try (SSLSocket sslSocket =
sslsf.createSocket("localhost", serverPort); (SSLSocket)sslsf.createSocket("localhost", serverPort)) {
InputStream sslIS = sslSocket.getInputStream(); InputStream sslIS = sslSocket.getInputStream();
OutputStream sslOS = sslSocket.getOutputStream(); OutputStream sslOS = sslSocket.getOutputStream();
sslOS.write(280); sslOS.write(280);
sslOS.flush(); sslOS.flush();
sslIS.read(); sslIS.read();
}
sslSocket.close();
} }
/* /*

@ -0,0 +1,158 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8145039
* @summary Check that marshalling of xjc generated class doesn't throw
* ClassCast exception.
* @modules javax.xml.bind
* @library /lib/testlibrary
* @run testng/othervm JaxbMarshallTest
*/
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import java.util.Arrays;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import jdk.testlibrary.JDKToolLauncher;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
public class JaxbMarshallTest {
@BeforeTest
public void setUp() throws IOException {
// Create test directory inside scratch
testWorkDir = Paths.get(System.getProperty("user.dir", "."));
// Save its URL
testWorkDirUrl = testWorkDir.toUri().toURL();
// Get test source directory path
testSrcDir = Paths.get(System.getProperty("test.src", "."));
// Get path of xjc result folder
xjcResultDir = testWorkDir.resolve(TEST_PACKAGE);
// Copy schema document file to scratch directory
Files.copy(testSrcDir.resolve(XSD_FILENAME), testWorkDir.resolve(XSD_FILENAME), REPLACE_EXISTING);
}
/*
* Test does the following steps to reproduce problem reported by 8145039:
* 1. Copy test schema to JTREG scratch folder
* 2. Run xjc on test schema file
* 3. Compile generated java files with test javac
* 4. Marshall the new list instance to ensure that
* ClassCastException is not thrown
*/
@Test
public void marshallClassCastExceptionTest() throws Exception {
JAXBContext jaxbContext;
Marshaller marshaller;
URLClassLoader jaxbContextClassLoader;
// Generate java classes by xjc
runXjc(XSD_FILENAME);
// Compile xjc generated java files
compileXjcGeneratedClasses();
// Create JAXB context based on xjc generated package.
// Need to create URL class loader ot make compiled classes discoverable
// by JAXB context
jaxbContextClassLoader = URLClassLoader.newInstance(new URL[] {testWorkDirUrl});
jaxbContext = JAXBContext.newInstance( TEST_PACKAGE, jaxbContextClassLoader);
// Create instance of Xjc generated data type.
// Java classes were compiled during the test execution hence reflection
// is needed here
Class classLongListClass = jaxbContextClassLoader.loadClass(TEST_CLASS);
Object objectLongListClass = classLongListClass.newInstance();
// Get 'getIn' method object
Method getInMethod = classLongListClass.getMethod( GET_LIST_METHOD, (Class [])null );
// Invoke 'getIn' method
List<Long> inList = (List<Long>)getInMethod.invoke(objectLongListClass);
// Add values into the jaxb object list
inList.add(Long.valueOf(0));
inList.add(Long.valueOf(43));
inList.add(Long.valueOf(1000000123));
// Marshall constructed complex type variable to standard output.
// In case of failure the ClassCastException will be thrown
marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(objectLongListClass, System.out);
}
// Compile schema file into java classes definitions
void runXjc(String xsdFileName) throws Exception {
// Prepare process builder to run schemagen tool and save its output
JDKToolLauncher xjcLauncher = JDKToolLauncher.createUsingTestJDK("xjc");
xjcLauncher.addToolArg(xsdFileName);
System.out.println("Executing xjc command: " + Arrays.asList(xjcLauncher.getCommand()));
ProcessBuilder pb = new ProcessBuilder(xjcLauncher.getCommand());
// Set xjc work directory with the input java file
pb.directory(testWorkDir.toFile());
pb.inheritIO();
Process p = pb.start();
p.waitFor();
p.destroy();
}
// Compile java classes with javac tool
void compileXjcGeneratedClasses() throws Exception {
JDKToolLauncher javacLauncher = JDKToolLauncher.createUsingTestJDK("javac");
javacLauncher.addToolArg(xjcResultDir.resolve("ObjectFactory.java").toString());
javacLauncher.addToolArg(xjcResultDir.resolve("TypesLongList.java").toString());
javacLauncher.addToolArg(xjcResultDir.resolve("package-info.java").toString());
System.out.println("Compiling xjc generated classes: " + Arrays.asList(javacLauncher.getCommand()));
ProcessBuilder pb = new ProcessBuilder(javacLauncher.getCommand());
pb.inheritIO();
pb.directory(testWorkDir.toFile());
Process p = pb.start();
p.waitFor();
p.destroy();
}
// Test schema filename
static final String XSD_FILENAME = "testSchema.xsd";
// Package of java classes generated by xjc
static final String TEST_PACKAGE = "testns_package";
// Name of generated java class
static final String TEST_CLASS = TEST_PACKAGE+".TypesLongList";
// Method to get the list from xjc generated class
static final String GET_LIST_METHOD = "getIn";
// Test working directory
Path testWorkDir;
// Test working directory URL
URL testWorkDirUrl;
// Directory with test src
Path testSrcDir;
// Directory with java files generated by xjc
Path xjcResultDir;
}

@ -0,0 +1,21 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://testns_package"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"
targetNamespace="http://testns_package">
<!-- Simple type list -->
<xsd:simpleType name="LongList">
<xsd:list>
<xsd:simpleType>
<xsd:restriction base="xsd:unsignedInt"/>
</xsd:simpleType>
</xsd:list>
</xsd:simpleType>
<!--- Complex test type -->
<xsd:element name="typesLongList">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="in" type="tns:LongList"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>

@ -23,14 +23,16 @@
/** /**
* @test * @test
* @bug 8080679 * @bug 8080679 8131913
* @modules jdk.internal.le/jdk.internal.jline.console * @modules jdk.internal.le/jdk.internal.jline
* jdk.internal.le/jdk.internal.jline.console
* @summary Verify ConsoleReader.stripAnsi strips escape sequences from its input correctly. * @summary Verify ConsoleReader.stripAnsi strips escape sequences from its input correctly.
*/ */
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import jdk.internal.jline.UnsupportedTerminal;
import jdk.internal.jline.console.ConsoleReader; import jdk.internal.jline.console.ConsoleReader;
public class StripAnsiTest { public class StripAnsiTest {
@ -41,7 +43,7 @@ public class StripAnsiTest {
void run() throws Exception { void run() throws Exception {
ByteArrayInputStream in = new ByteArrayInputStream(new byte[0]); ByteArrayInputStream in = new ByteArrayInputStream(new byte[0]);
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
ConsoleReader reader = new ConsoleReader(in, out); ConsoleReader reader = new ConsoleReader(in, out, new UnsupportedTerminal());
String withAnsi = "0\033[s1\033[2J2\033[37;4m3"; String withAnsi = "0\033[s1\033[2J2\033[37;4m3";
String expected = "0123"; String expected = "0123";

@ -0,0 +1,607 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import jdk.internal.misc.Unsafe;
import java.lang.reflect.Field;
/**
* Helper class to support testing of Unsafe.copyMemory and Unsafe.copySwapMemory
*/
public class CopyCommon {
private static final boolean DEBUG = Boolean.getBoolean("CopyCommon.DEBUG");
public static final long KB = 1024;
public static final long MB = KB * 1024;
public static final long GB = MB * 1024;
static final int SMALL_COPY_SIZE = 32;
static final int BASE_ALIGNMENT = 16;
protected static final Unsafe UNSAFE;
static {
try {
Field f = jdk.internal.misc.Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
UNSAFE = (jdk.internal.misc.Unsafe) f.get(null);
} catch (Exception e) {
throw new RuntimeException("Unable to get Unsafe instance.", e);
}
}
static long alignDown(long value, long alignment) {
return value & ~(alignment - 1);
}
static long alignUp(long value, long alignment) {
return (value + alignment - 1) & ~(alignment - 1);
}
static boolean isAligned(long value, long alignment) {
return value == alignDown(value, alignment);
}
CopyCommon() {
}
/**
* Generate verification data for a given offset
*
* The verification data is used to verify that the correct bytes
* have indeed been copied and byte swapped.
*
* The data is generated based on the offset (in bytes) into the
* source buffer. For a native buffer the offset is relative to
* the base pointer. For a heap array it is relative to the
* address of the first array element.
*
* This method will return the result of doing an elementSize byte
* read starting at offset (in bytes).
*
* @param offset offset into buffer
* @param elemSize size (in bytes) of the element
*
* @return the verification data, only the least significant
* elemSize*8 bits are set, zero extended
*/
private long getVerificationDataForOffset(long offset, long elemSize) {
byte[] bytes = new byte[(int)elemSize];
for (long i = 0; i < elemSize; i++) {
bytes[(int)i] = (byte)(offset + i);
}
long o = UNSAFE.arrayBaseOffset(byte[].class);
switch ((int)elemSize) {
case 1: return Byte.toUnsignedLong(UNSAFE.getByte(bytes, o));
case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(bytes, o));
case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(bytes, o));
case 8: return UNSAFE.getLongUnaligned(bytes, o);
default: throw new IllegalArgumentException("Invalid element size: " + elemSize);
}
}
/**
* Verify byte swapped data
*
* @param ptr the data to verify
* @param srcOffset the srcOffset (in bytes) from which the copy started,
* used as key to regenerate the verification data
* @param dstOffset the offset (in bytes) in the array at which to start
* the verification, relative to the first element in the array
* @param size size (in bytes) of data to to verify
* @param elemSize size (in bytes) of the individual array elements
*
* @throws RuntimeException if an error is found
*/
private void verifySwappedData(GenericPointer ptr, long srcOffset, long dstOffset, long size, long elemSize) {
for (long offset = 0; offset < size; offset += elemSize) {
long expectedUnswapped = getVerificationDataForOffset(srcOffset + offset, elemSize);
long expected = byteSwap(expectedUnswapped, elemSize);
long actual = getArrayElem(ptr, dstOffset + offset, elemSize);
if (expected != actual) {
throw new RuntimeException("srcOffset: 0x" + Long.toHexString(srcOffset) +
" dstOffset: 0x" + Long.toHexString(dstOffset) +
" size: 0x" + Long.toHexString(size) +
" offset: 0x" + Long.toHexString(offset) +
" expectedUnswapped: 0x" + Long.toHexString(expectedUnswapped) +
" expected: 0x" + Long.toHexString(expected) +
" != actual: 0x" + Long.toHexString(actual));
}
}
}
/**
* Initialize an array with verification friendly data
*
* @param ptr pointer to the data to initialize
* @param size size (in bytes) of the data
* @param elemSize size (in bytes) of the individual elements
*/
private void initVerificationData(GenericPointer ptr, long size, long elemSize) {
for (long offset = 0; offset < size; offset++) {
byte data = (byte)getVerificationDataForOffset(offset, 1);
if (ptr.isOnHeap()) {
UNSAFE.putByte(ptr.getObject(), ptr.getOffset() + offset, data);
} else {
UNSAFE.putByte(ptr.getOffset() + offset, data);
}
}
}
/**
* Allocate a primitive array
*
* @param size size (in bytes) of all the array elements (elemSize * length)
* @param elemSize the size of the array elements
*
* @return a newly allocated primitive array
*/
Object allocArray(long size, long elemSize) {
int length = (int)(size / elemSize);
switch ((int)elemSize) {
case 1: return new byte[length];
case 2: return new short[length];
case 4: return new int[length];
case 8: return new long[length];
default:
throw new IllegalArgumentException("Invalid element size: " + elemSize);
}
}
/**
* Get the value of a primitive array entry
*
* @param ptr pointer to the data
* @param offset offset (in bytes) of the array element, relative to the first element in the array
*
* @return the array element, as an unsigned long
*/
private long getArrayElem(GenericPointer ptr, long offset, long elemSize) {
if (ptr.isOnHeap()) {
Object o = ptr.getObject();
int index = (int)(offset / elemSize);
if (o instanceof short[]) {
short[] arr = (short[])o;
return Short.toUnsignedLong(arr[index]);
} else if (o instanceof int[]) {
int[] arr = (int[])o;
return Integer.toUnsignedLong(arr[index]);
} else if (o instanceof long[]) {
long[] arr = (long[])o;
return arr[index];
} else {
throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName());
}
} else {
long addr = ptr.getOffset() + offset;
switch ((int)elemSize) {
case 1: return Byte.toUnsignedLong(UNSAFE.getByte(addr));
case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(null, addr));
case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(null, addr));
case 8: return UNSAFE.getLongUnaligned(null, addr);
default: throw new IllegalArgumentException("Invalid element size: " + elemSize);
}
}
}
private void putValue(long addr, long elemSize, long value) {
switch ((int)elemSize) {
case 1: UNSAFE.putByte(addr, (byte)value); break;
case 2: UNSAFE.putShortUnaligned(null, addr, (short)value); break;
case 4: UNSAFE.putIntUnaligned(null, addr, (int)value); break;
case 8: UNSAFE.putLongUnaligned(null, addr, value); break;
default: throw new IllegalArgumentException("Invalid element size: " + elemSize);
}
}
/**
* Get the size of the elements for an array
*
* @param o a primitive heap array
*
* @return the size (in bytes) of the individual array elements
*/
private long getArrayElemSize(Object o) {
if (o instanceof short[]) {
return 2;
} else if (o instanceof int[]) {
return 4;
} else if (o instanceof long[]) {
return 8;
} else {
throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName());
}
}
/**
* Byte swap a value
*
* @param value the value to swap, only the bytes*8 least significant bits are used
* @param size size (in bytes) of the value
*
* @return the byte swapped value in the bytes*8 least significant bits
*/
private long byteSwap(long value, long size) {
switch ((int)size) {
case 2: return Short.toUnsignedLong(Short.reverseBytes((short)value));
case 4: return Integer.toUnsignedLong(Integer.reverseBytes((int)value));
case 8: return Long.reverseBytes(value);
default: throw new IllegalArgumentException("Invalid element size: " + size);
}
}
/**
* Verify data which has *not* been byte swapped
*
* @param ptr the data to verify
* @param startOffset the offset (in bytes) at which to start the verification
* @param size size (in bytes) of the data to verify
*
* @throws RuntimeException if an error is found
*/
private void verifyUnswappedData(GenericPointer ptr, long startOffset, long srcOffset, long size) {
for (long i = 0; i < size; i++) {
byte expected = (byte)getVerificationDataForOffset(srcOffset + i, 1);
byte actual;
if (ptr.isOnHeap()) {
actual = UNSAFE.getByte(ptr.getObject(), ptr.getOffset() + startOffset + i);
} else {
actual = UNSAFE.getByte(ptr.getOffset() + startOffset + i);
}
if (expected != actual) {
throw new RuntimeException("startOffset: 0x" + Long.toHexString(startOffset) +
" srcOffset: 0x" + Long.toHexString(srcOffset) +
" size: 0x" + Long.toHexString(size) +
" i: 0x" + Long.toHexString(i) +
" expected: 0x" + Long.toHexString(expected) +
" != actual: 0x" + Long.toHexString(actual));
}
}
}
/**
* Copy and byte swap data from the source to the destination
*
* This method will pre-populate the whole source and destination
* buffers with verification friendly data. It will then copy data
* to fill part of the destination buffer with data from the
* source, optionally byte swapping the copied elements on the
* fly. Some space (padding) will be left before and after the
* data in the destination buffer, which should not be
* touched/overwritten by the copy call.
*
* Note: Both source and destination buffers will be overwritten!
*
* @param src source buffer to copy from
* @param srcOffset the offset (in bytes) in the source buffer, relative to
* the first array element, at which to start reading data
* @param dst destination buffer to copy to
* @param dstOffset the offset (in bytes) in the destination
* buffer, relative to the first array element, at which to
* start writing data
* @param bufSize the size (in bytes) of the src and dst arrays
* @param copyBytes the size (in bytes) of the copy to perform,
* must be a multiple of elemSize
* @param elemSize the size (in bytes) of the elements
* @param swap true if elements should be byte swapped
*
* @throws RuntimeException if an error is found
*/
void testCopyGeneric(GenericPointer src, long srcOffset,
GenericPointer dst, long dstOffset,
long bufSize, long copyBytes, long elemSize, boolean swap) {
if (swap) {
if (!isAligned(copyBytes, elemSize)) {
throw new IllegalArgumentException(
"copyBytes (" + copyBytes + ") must be a multiple of elemSize (" + elemSize + ")");
}
if (src.isOnHeap() && !isAligned(srcOffset, elemSize)) {
throw new IllegalArgumentException(
"srcOffset (" + srcOffset + ") must be a multiple of elemSize (" + elemSize + ")");
}
if (dst.isOnHeap() && !isAligned(dstOffset, elemSize)) {
throw new IllegalArgumentException(
"dstOffset (" + dstOffset + ") must be a multiple of elemSize (" + elemSize + ")");
}
}
if (srcOffset + copyBytes > bufSize) {
throw new IllegalArgumentException(
"srcOffset (" + srcOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")");
}
if (dstOffset + copyBytes > bufSize) {
throw new IllegalArgumentException(
"dstOffset (" + dstOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")");
}
// Initialize the whole source buffer with a verification friendly pattern (no 0x00 bytes)
initVerificationData(src, bufSize, elemSize);
if (!src.equals(dst)) {
initVerificationData(dst, bufSize, elemSize);
}
if (DEBUG) {
System.out.println("===before===");
for (int offset = 0; offset < bufSize; offset += elemSize) {
long srcValue = getArrayElem(src, offset, elemSize);
long dstValue = getArrayElem(dst, offset, elemSize);
System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) +
" src=0x" + Long.toHexString(srcValue) +
" dst=0x" + Long.toHexString(dstValue));
}
}
if (swap) {
// Copy & swap data into the middle of the destination buffer
UNSAFE.copySwapMemory(src.getObject(),
src.getOffset() + srcOffset,
dst.getObject(),
dst.getOffset() + dstOffset,
copyBytes,
elemSize);
} else {
// Copy & swap data into the middle of the destination buffer
UNSAFE.copyMemory(src.getObject(),
src.getOffset() + srcOffset,
dst.getObject(),
dst.getOffset() + dstOffset,
copyBytes);
}
if (DEBUG) {
System.out.println("===after===");
for (int offset = 0; offset < bufSize; offset += elemSize) {
long srcValue = getArrayElem(src, offset, elemSize);
long dstValue = getArrayElem(dst, offset, elemSize);
System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) +
" src=0x" + Long.toHexString(srcValue) +
" dst=0x" + Long.toHexString(dstValue));
}
}
// Verify the the front padding is unchanged
verifyUnswappedData(dst, 0, 0, dstOffset);
if (swap) {
// Verify swapped data
verifySwappedData(dst, srcOffset, dstOffset, copyBytes, elemSize);
} else {
// Verify copied/unswapped data
verifyUnswappedData(dst, dstOffset, srcOffset, copyBytes);
}
// Verify that the back padding is unchanged
long frontAndCopyBytes = dstOffset + copyBytes;
long trailingBytes = bufSize - frontAndCopyBytes;
verifyUnswappedData(dst, frontAndCopyBytes, frontAndCopyBytes, trailingBytes);
}
/**
* Test various configurations of copying and optionally swapping data
*
* @param src the source buffer to copy from
* @param dst the destination buffer to copy to
* @param size size (in bytes) of the buffers
* @param elemSize size (in bytes) of the individual elements
*
* @throws RuntimeException if an error is found
*/
public void testBufferPair(GenericPointer src, GenericPointer dst, long size, long elemSize, boolean swap) {
// offset in source from which to start reading data
for (long srcOffset = 0; srcOffset < size; srcOffset += (src.isOnHeap() ? elemSize : 1)) {
// offset in destination at which to start writing data
for (int dstOffset = 0; dstOffset < size; dstOffset += (dst.isOnHeap() ? elemSize : 1)) {
// number of bytes to copy
long maxCopyBytes = Math.min(size - srcOffset, size - dstOffset);
for (long copyBytes = 0; copyBytes < maxCopyBytes; copyBytes += elemSize) {
try {
testCopyGeneric(src, srcOffset, dst, dstOffset, size, copyBytes, elemSize, swap);
} catch (RuntimeException e) {
// Wrap the exception in another exception to catch the relevant configuration data
throw new RuntimeException("testBufferPair: " +
"src=" + src +
" dst=" + dst +
" elemSize=0x" + Long.toHexString(elemSize) +
" copyBytes=0x" + Long.toHexString(copyBytes) +
" srcOffset=0x" + Long.toHexString(srcOffset) +
" dstOffset=0x" + Long.toHexString(dstOffset) +
" swap=" + swap,
e);
}
}
}
}
}
/**
* Test copying between various permutations of buffers
*
* @param buffers buffers to permute (src x dst)
* @param size size (in bytes) of buffers
* @param elemSize size (in bytes) of individual elements
*
* @throws RuntimeException if an error is found
*/
public void testPermuteBuffers(GenericPointer[] buffers, long size, long elemSize, boolean swap) {
System.out.println("testPermuteBuffers(buffers, " + size + ", " + elemSize + ", " + swap + ")");
for (int srcIndex = 0; srcIndex < buffers.length; srcIndex++) {
for (int dstIndex = 0; dstIndex < buffers.length; dstIndex++) {
testBufferPair(buffers[srcIndex], buffers[dstIndex], size, elemSize, swap);
}
}
}
/**
* Test copying of a specific element size
*
* @param size size (in bytes) of buffers to allocate
* @param elemSize size (in bytes) of individual elements
*
* @throws RuntimeException if an error is found
*/
private void testElemSize(long size, long elemSize, boolean swap) {
long buf1Raw = 0;
long buf2Raw = 0;
try {
buf1Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT);
long buf1 = alignUp(buf1Raw, BASE_ALIGNMENT);
buf2Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT);
long buf2 = alignUp(buf2Raw, BASE_ALIGNMENT);
GenericPointer[] buffers = {
new GenericPointer(buf1),
new GenericPointer(buf2),
new GenericPointer(allocArray(size, elemSize)),
new GenericPointer(allocArray(size, elemSize))
};
testPermuteBuffers(buffers, size, elemSize, swap);
} finally {
if (buf1Raw != 0) {
UNSAFE.freeMemory(buf1Raw);
}
if (buf2Raw != 0) {
UNSAFE.freeMemory(buf2Raw);
}
}
}
/**
* Verify that small copies work
*/
void testSmallCopy(boolean swap) {
int smallBufSize = SMALL_COPY_SIZE;
int minElemSize = swap ? 2 : 1;
int maxElemSize = swap ? 8 : 1;
// Test various element types and heap/native combinations
for (long elemSize = minElemSize; elemSize <= maxElemSize; elemSize <<= 1) {
testElemSize(smallBufSize, elemSize, swap);
}
}
/**
* Verify that large copies work
*/
void testLargeCopy(boolean swap) {
long size = 2 * GB + 8;
long bufRaw = 0;
// Check that a large native copy succeeds
try {
try {
bufRaw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT);
} catch (OutOfMemoryError e) {
// Accept failure, skip test
return;
}
long buf = alignUp(bufRaw, BASE_ALIGNMENT);
if (swap) {
UNSAFE.copySwapMemory(null, buf, null, buf, size, 8);
} else {
UNSAFE.copyMemory(null, buf, null, buf, size);
}
} catch (Exception e) {
throw new RuntimeException("copy of large buffer failed (swap=" + swap + ")");
} finally {
if (bufRaw != 0) {
UNSAFE.freeMemory(bufRaw);
}
}
}
/**
* Helper class to represent a "pointer" - either a heap array or
* a pointer to a native buffer.
*
* In the case of a native pointer, the Object is null and the offset is
* the absolute address of the native buffer.
*
* In the case of a heap object, the Object is a primitive array, and
* the offset will be set to the base offset to the first element, meaning
* the object and the offset together form a double-register pointer.
*/
static class GenericPointer {
private final Object o;
private final long offset;
private GenericPointer(Object o, long offset) {
this.o = o;
this.offset = offset;
}
public String toString() {
return "GenericPointer(o={" + o + "}, offset=0x" + Long.toHexString(offset) + ")";
}
public boolean equals(Object other) {
if (!(other instanceof GenericPointer)) {
return false;
}
GenericPointer otherp = (GenericPointer)other;
return o == otherp.o && offset == otherp.offset;
}
GenericPointer(Object o) {
this(o, UNSAFE.arrayBaseOffset(o.getClass()));
}
GenericPointer(long offset) {
this(null, offset);
}
public boolean isOnHeap() {
return o != null;
}
public Object getObject() {
return o;
}
public long getOffset() {
return offset;
}
}
}

@ -0,0 +1,138 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import jdk.internal.misc.Unsafe;
import java.lang.reflect.Field;
/*
* @test
* @summary Test Unsafe.copyMemory
* @modules java.base/jdk.internal.misc
*/
public class CopyMemory extends CopyCommon {
private CopyMemory() {
}
/**
* Run positive tests
*
* @throws RuntimeException if an error is found
*/
private void testPositive() {
testSmallCopy(false);
testLargeCopy(false);
}
/**
* Run negative tests, testing corner cases and the various exceptions
*
* @throws RuntimeException if an error is found
*/
private void testNegative() {
long bufRaw = 0;
try {
bufRaw = UNSAFE.allocateMemory(1024);
long buf = CopyCommon.alignUp(bufRaw, CopyCommon.BASE_ALIGNMENT);
short[] arr = new short[16];
// Check illegal sizes
System.out.println("Testing negative size");
try {
UNSAFE.copyMemory(null, buf, null, buf, -1);
throw new RuntimeException("copyMemory failed to throw IAE for size=-1");
} catch (IllegalArgumentException e) {
// good
}
System.out.println("Testing negative srcOffset");
try {
// Check that negative srcOffset throws an IAE
UNSAFE.copyMemory(arr, -1, arr, UNSAFE.arrayBaseOffset(arr.getClass()), 16);
throw new RuntimeException("copyMemory failed to throw IAE for srcOffset=-1");
} catch (IllegalArgumentException e) {
// good
}
System.out.println("Testing negative destOffset");
try {
// Check that negative dstOffset throws an IAE
UNSAFE.copyMemory(arr, UNSAFE.arrayBaseOffset(arr.getClass()), arr, -1, 16);
throw new RuntimeException("copyMemory failed to throw IAE for destOffset=-1");
} catch (IllegalArgumentException e) {
// good
}
System.out.println("Testing reference array");
try {
// Check that a reference array destination throws IAE
UNSAFE.copyMemory(null, buf, new Object[16], UNSAFE.arrayBaseOffset(Object[].class), 16);
throw new RuntimeException("copyMemory failed to throw IAE");
} catch (IllegalArgumentException e) {
// good
}
// Check that invalid source & dest pointers throw IAEs (only relevant on 32-bit platforms)
if (UNSAFE.addressSize() == 4) {
long invalidPtr = (long)1 << 35; // Pick a random bit in upper 32 bits
try {
// Check that an invalid (not 32-bit clean) source pointer throws IAE
UNSAFE.copyMemory(null, invalidPtr, null, buf, 16);
throw new RuntimeException("copyMemory failed to throw IAE for srcOffset 0x" +
Long.toHexString(invalidPtr));
} catch (IllegalArgumentException e) {
// good
}
try {
// Check that an invalid (not 32-bit clean) source pointer throws IAE
UNSAFE.copyMemory(null, buf, null, invalidPtr, 16);
throw new RuntimeException("copyMemory failed to throw IAE for destOffset 0x" +
Long.toHexString(invalidPtr));
} catch (IllegalArgumentException e) {
// good
}
}
} finally {
if (bufRaw != 0) {
UNSAFE.freeMemory(bufRaw);
}
}
}
/**
* Run all tests
*
* @throws RuntimeException if an error is found
*/
private void test() {
testPositive();
testNegative();
}
public static void main(String[] args) {
CopyMemory cs = new CopyMemory();
cs.test();
}
}

@ -29,507 +29,18 @@ import java.lang.reflect.Field;
* @summary Test Unsafe.copySwapMemory * @summary Test Unsafe.copySwapMemory
* @modules java.base/jdk.internal.misc * @modules java.base/jdk.internal.misc
*/ */
public class CopySwap { public class CopySwap extends CopyCommon {
private static final boolean DEBUG = Boolean.getBoolean("CopySwap.DEBUG");
public static final long KB = 1024;
public static final long MB = KB * 1024;
public static final long GB = MB * 1024;
private static final Unsafe UNSAFE;
private static final int SMALL_COPY_SIZE = 32;
private static final int BASE_ALIGNMENT = 16;
static {
try {
Field f = jdk.internal.misc.Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
UNSAFE = (jdk.internal.misc.Unsafe) f.get(null);
} catch (Exception e) {
throw new RuntimeException("Unable to get Unsafe instance.", e);
}
}
private static long alignDown(long value, long alignment) {
return value & ~(alignment - 1);
}
private static long alignUp(long value, long alignment) {
return (value + alignment - 1) & ~(alignment - 1);
}
private static boolean isAligned(long value, long alignment) {
return value == alignDown(value, alignment);
}
private CopySwap() { private CopySwap() {
} }
/**
* Generate verification data for a given offset
*
* The verification data is used to verify that the correct bytes
* have indeed been copied and byte swapped.
*
* The data is generated based on the offset (in bytes) into the
* source buffer. For a native buffer the offset is relative to
* the base pointer. For a heap array it is relative to the
* address of the first array element.
*
* This method will return the result of doing an elementSize byte
* read starting at offset (in bytes).
*
* @param offset offset into buffer
* @param elemSize size (in bytes) of the element
*
* @return the verification data, only the least significant
* elemSize*8 bits are set, zero extended
*/
private long getVerificationDataForOffset(long offset, long elemSize) {
byte[] bytes = new byte[(int)elemSize];
for (long i = 0; i < elemSize; i++) {
bytes[(int)i] = (byte)(offset + i);
}
long o = UNSAFE.arrayBaseOffset(byte[].class);
switch ((int)elemSize) {
case 1: return Byte.toUnsignedLong(UNSAFE.getByte(bytes, o));
case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(bytes, o));
case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(bytes, o));
case 8: return UNSAFE.getLongUnaligned(bytes, o);
default: throw new IllegalArgumentException("Invalid element size: " + elemSize);
}
}
/**
* Verify byte swapped data
*
* @param ptr the data to verify
* @param srcOffset the srcOffset (in bytes) from which the copy started,
* used as key to regenerate the verification data
* @param dstOffset the offset (in bytes) in the array at which to start
* the verification, relative to the first element in the array
* @param size size (in bytes) of data to to verify
* @param elemSize size (in bytes) of the individual array elements
*
* @throws RuntimeException if an error is found
*/
private void verifySwappedData(GenericPointer ptr, long srcOffset, long dstOffset, long size, long elemSize) {
for (long offset = 0; offset < size; offset += elemSize) {
long expectedUnswapped = getVerificationDataForOffset(srcOffset + offset, elemSize);
long expected = byteSwap(expectedUnswapped, elemSize);
long actual = getArrayElem(ptr, dstOffset + offset, elemSize);
if (expected != actual) {
throw new RuntimeException("srcOffset: 0x" + Long.toHexString(srcOffset) +
" dstOffset: 0x" + Long.toHexString(dstOffset) +
" size: 0x" + Long.toHexString(size) +
" offset: 0x" + Long.toHexString(offset) +
" expectedUnswapped: 0x" + Long.toHexString(expectedUnswapped) +
" expected: 0x" + Long.toHexString(expected) +
" != actual: 0x" + Long.toHexString(actual));
}
}
}
/**
* Initialize an array with verification friendly data
*
* @param ptr pointer to the data to initialize
* @param size size (in bytes) of the data
* @param elemSize size (in bytes) of the individual elements
*/
private void initVerificationData(GenericPointer ptr, long size, long elemSize) {
for (long offset = 0; offset < size; offset++) {
byte data = (byte)getVerificationDataForOffset(offset, 1);
if (ptr.isOnHeap()) {
UNSAFE.putByte(ptr.getObject(), ptr.getOffset() + offset, data);
} else {
UNSAFE.putByte(ptr.getOffset() + offset, data);
}
}
}
/**
* Allocate a primitive array
*
* @param size size (in bytes) of all the array elements (elemSize * length)
* @param elemSize the size of the array elements
*
* @return a newly allocated primitive array
*/
Object allocArray(long size, long elemSize) {
int length = (int)(size / elemSize);
switch ((int)elemSize) {
case 2: return new short[length];
case 4: return new int[length];
case 8: return new long[length];
default:
throw new IllegalArgumentException("Invalid element size: " + elemSize);
}
}
/**
* Get the value of a primitive array entry
*
* @param ptr pointer to the data
* @param offset offset (in bytes) of the array element, relative to the first element in the array
*
* @return the array element, as an unsigned long
*/
private long getArrayElem(GenericPointer ptr, long offset, long elemSize) {
if (ptr.isOnHeap()) {
Object o = ptr.getObject();
int index = (int)(offset / elemSize);
if (o instanceof short[]) {
short[] arr = (short[])o;
return Short.toUnsignedLong(arr[index]);
} else if (o instanceof int[]) {
int[] arr = (int[])o;
return Integer.toUnsignedLong(arr[index]);
} else if (o instanceof long[]) {
long[] arr = (long[])o;
return arr[index];
} else {
throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName());
}
} else {
long addr = ptr.getOffset() + offset;
switch ((int)elemSize) {
case 1: return Byte.toUnsignedLong(UNSAFE.getByte(addr));
case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(null, addr));
case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(null, addr));
case 8: return UNSAFE.getLongUnaligned(null, addr);
default: throw new IllegalArgumentException("Invalid element size: " + elemSize);
}
}
}
private void putValue(long addr, long elemSize, long value) {
switch ((int)elemSize) {
case 1: UNSAFE.putByte(addr, (byte)value); break;
case 2: UNSAFE.putShortUnaligned(null, addr, (short)value); break;
case 4: UNSAFE.putIntUnaligned(null, addr, (int)value); break;
case 8: UNSAFE.putLongUnaligned(null, addr, value); break;
default: throw new IllegalArgumentException("Invalid element size: " + elemSize);
}
}
/**
* Get the size of the elements for an array
*
* @param o a primitive heap array
*
* @return the size (in bytes) of the individual array elements
*/
private long getArrayElemSize(Object o) {
if (o instanceof short[]) {
return 2;
} else if (o instanceof int[]) {
return 4;
} else if (o instanceof long[]) {
return 8;
} else {
throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName());
}
}
/**
* Byte swap a value
*
* @param value the value to swap, only the bytes*8 least significant bits are used
* @param size size (in bytes) of the value
*
* @return the byte swapped value in the bytes*8 least significant bits
*/
private long byteSwap(long value, long size) {
switch ((int)size) {
case 2: return Short.toUnsignedLong(Short.reverseBytes((short)value));
case 4: return Integer.toUnsignedLong(Integer.reverseBytes((int)value));
case 8: return Long.reverseBytes(value);
default: throw new IllegalArgumentException("Invalid element size: " + size);
}
}
/**
* Verify data in a heap array which has *not* been byte swapped
*
* @param ptr the data to verify
* @param startOffset the offset (in bytes) at which to start the verification
* @param size size (in bytes) of the data to verify
*
* @throws RuntimeException if an error is found
*/
private void verifyUnswappedData(GenericPointer ptr, long startOffset, long size) {
for (long elemOffset = startOffset; elemOffset < startOffset + size; elemOffset++) {
byte expected = (byte)getVerificationDataForOffset(elemOffset, 1);
byte actual;
if (ptr.isOnHeap()) {
actual = UNSAFE.getByte(ptr.getObject(), ptr.getOffset() + elemOffset);
} else {
actual = UNSAFE.getByte(ptr.getOffset() + elemOffset);
}
if (expected != actual) {
throw new RuntimeException("startOffset: 0x" + Long.toHexString(startOffset) +
" size: 0x" + Long.toHexString(size) +
" elemOffset: 0x" + Long.toHexString(elemOffset) +
" expected: 0x" + Long.toHexString(expected) +
" != actual: 0x" + Long.toHexString(actual));
}
}
}
/**
* Copy and byte swap data from the source to the destination
*
* This method will pre-populate the whole source and destination
* buffers with verification friendly data. It will then use
* copySwapMemory to fill part of the destination buffer with
* swapped data from the source. Some space (padding) will be
* left before and after the data in the destination buffer, which
* should not be touched/overwritten by the copy call.
*
* Note: Both source and destination buffers will be overwritten!
*
* @param src source buffer to copy from
* @param srcOffset the offset (in bytes) in the source buffer, relative to
* the first array element, at which to start reading data
* @param dst destination buffer to copy to
* @param dstOffset the offset (in bytes) in the destination
* buffer, relative to the first array element, at which to
* start writing data
* @param bufSize the size (in bytes) of the src and dst arrays
* @param copyBytes the size (in bytes) of the copy to perform,
* must be a multiple of elemSize
* @param elemSize the size (in bytes) of the elements to byte swap
*
* @throws RuntimeException if an error is found
*/
private void testCopySwap(GenericPointer src, long srcOffset,
GenericPointer dst, long dstOffset,
long bufSize, long copyBytes, long elemSize) {
if (!isAligned(copyBytes, elemSize)) {
throw new IllegalArgumentException(
"copyBytes (" + copyBytes + ") must be a multiple of elemSize (" + elemSize + ")");
}
if (src.isOnHeap() && !isAligned(srcOffset, elemSize)) {
throw new IllegalArgumentException(
"srcOffset (" + srcOffset + ") must be a multiple of elemSize (" + elemSize + ")");
}
if (dst.isOnHeap() && !isAligned(dstOffset, elemSize)) {
throw new IllegalArgumentException(
"dstOffset (" + dstOffset + ") must be a multiple of elemSize (" + elemSize + ")");
}
if (srcOffset + copyBytes > bufSize) {
throw new IllegalArgumentException(
"srcOffset (" + srcOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")");
}
if (dstOffset + copyBytes > bufSize) {
throw new IllegalArgumentException(
"dstOffset (" + dstOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")");
}
// Initialize the whole source buffer with a verification friendly pattern (no 0x00 bytes)
initVerificationData(src, bufSize, elemSize);
if (!src.equals(dst)) {
initVerificationData(dst, bufSize, elemSize);
}
if (DEBUG) {
System.out.println("===before===");
for (int offset = 0; offset < bufSize; offset += elemSize) {
long srcValue = getArrayElem(src, offset, elemSize);
long dstValue = getArrayElem(dst, offset, elemSize);
System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) +
" src=0x" + Long.toHexString(srcValue) +
" dst=0x" + Long.toHexString(dstValue));
}
}
// Copy & swap data into the middle of the destination buffer
UNSAFE.copySwapMemory(src.getObject(),
src.getOffset() + srcOffset,
dst.getObject(),
dst.getOffset() + dstOffset,
copyBytes,
elemSize);
if (DEBUG) {
System.out.println("===after===");
for (int offset = 0; offset < bufSize; offset += elemSize) {
long srcValue = getArrayElem(src, offset, elemSize);
long dstValue = getArrayElem(dst, offset, elemSize);
System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) +
" src=0x" + Long.toHexString(srcValue) +
" dst=0x" + Long.toHexString(dstValue));
}
}
// Verify the the front padding is unchanged
verifyUnswappedData(dst, 0, dstOffset);
// Verify swapped data
verifySwappedData(dst, srcOffset, dstOffset, copyBytes, elemSize);
// Verify that the back back padding is unchanged
long frontAndDataBytes = dstOffset + copyBytes;
long trailingBytes = bufSize - frontAndDataBytes;
verifyUnswappedData(dst, frontAndDataBytes, trailingBytes);
}
/**
* Test various configurations copy-swapping from one buffer to the other
*
* @param src the source buffer to copy from
* @param dst the destination buffer to copy to
* @param size size (in bytes) of the buffers
* @param elemSize size (in bytes) of the individual elements
*
* @throws RuntimeException if an error is found
*/
public void testBufferPair(GenericPointer src, GenericPointer dst, long size, long elemSize) {
// offset in source from which to start reading data
for (long srcOffset = 0; srcOffset < size; srcOffset += (src.isOnHeap() ? elemSize : 1)) {
// offset in destination at which to start writing data
for (int dstOffset = 0; dstOffset < size; dstOffset += (dst.isOnHeap() ? elemSize : 1)) {
// number of bytes to copy
long maxCopyBytes = Math.min(size - srcOffset, size - dstOffset);
for (long copyBytes = 0; copyBytes < maxCopyBytes; copyBytes += elemSize) {
try {
testCopySwap(src, srcOffset, dst, dstOffset, size, copyBytes, elemSize);
} catch (RuntimeException e) {
// Wrap the exception in another exception to catch the relevant configuration data
throw new RuntimeException("testBufferPair: " +
"src=" + src +
" dst=" + dst +
" elemSize=0x" + Long.toHexString(elemSize) +
" copyBytes=0x" + Long.toHexString(copyBytes) +
" srcOffset=0x" + Long.toHexString(srcOffset) +
" dstOffset=0x" + Long.toHexString(dstOffset),
e);
}
}
}
}
}
/**
* Test copying between various permutations of buffers
*
* @param buffers buffers to permute (src x dst)
* @param size size (in bytes) of buffers
* @param elemSize size (in bytes) of individual elements
*
* @throws RuntimeException if an error is found
*/
public void testPermuteBuffers(GenericPointer[] buffers, long size, long elemSize) {
for (int srcIndex = 0; srcIndex < buffers.length; srcIndex++) {
for (int dstIndex = 0; dstIndex < buffers.length; dstIndex++) {
testBufferPair(buffers[srcIndex], buffers[dstIndex], size, elemSize);
}
}
}
/**
* Test copying of a specific element size
*
* @param size size (in bytes) of buffers to allocate
* @param elemSize size (in bytes) of individual elements
*
* @throws RuntimeException if an error is found
*/
private void testElemSize(long size, long elemSize) {
long buf1Raw = 0;
long buf2Raw = 0;
try {
buf1Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT);
long buf1 = alignUp(buf1Raw, BASE_ALIGNMENT);
buf2Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT);
long buf2 = alignUp(buf2Raw, BASE_ALIGNMENT);
GenericPointer[] buffers = {
new GenericPointer(buf1),
new GenericPointer(buf2),
new GenericPointer(allocArray(size, elemSize)),
new GenericPointer(allocArray(size, elemSize))
};
testPermuteBuffers(buffers, size, elemSize);
} finally {
if (buf1Raw != 0) {
UNSAFE.freeMemory(buf1Raw);
}
if (buf2Raw != 0) {
UNSAFE.freeMemory(buf2Raw);
}
}
}
/**
* Verify that small copy swaps work
*/
private void testSmallCopy() {
int smallBufSize = SMALL_COPY_SIZE;
// Test various element types and heap/native combinations
for (long elemSize = 2; elemSize <= 8; elemSize <<= 1) {
testElemSize(smallBufSize, elemSize);
}
}
/**
* Verify that large copy swaps work
*/
private void testLargeCopy() {
long size = 2 * GB + 8;
long bufRaw = 0;
// Check that a large native copy succeeds
try {
try {
bufRaw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT);
} catch (OutOfMemoryError e) {
// Accept failure, skip test
return;
}
long buf = alignUp(bufRaw, BASE_ALIGNMENT);
UNSAFE.copySwapMemory(null, buf, null, buf, size, 8);
} catch (Exception e) {
throw new RuntimeException("copySwapMemory of large buffer failed");
} finally {
if (bufRaw != 0) {
UNSAFE.freeMemory(bufRaw);
}
}
}
/** /**
* Run positive tests * Run positive tests
* *
* @throws RuntimeException if an error is found * @throws RuntimeException if an error is found
*/ */
private void testPositive() { private void testPositive() {
testSmallCopy(); testSmallCopy(true);
testLargeCopy(); testLargeCopy(true);
} }
/** /**
@ -542,7 +53,7 @@ public class CopySwap {
try { try {
bufRaw = UNSAFE.allocateMemory(1024); bufRaw = UNSAFE.allocateMemory(1024);
long buf = alignUp(bufRaw, BASE_ALIGNMENT); long buf = CopyCommon.alignUp(bufRaw, CopyCommon.BASE_ALIGNMENT);
short[] arr = new short[16]; short[] arr = new short[16];
// Check various illegal element sizes // Check various illegal element sizes
@ -586,22 +97,6 @@ public class CopySwap {
} }
} }
try {
// Check that a NULL source throws NPE
UNSAFE.copySwapMemory(null, 0, null, buf, 16, 2);
throw new RuntimeException("copySwapMemory failed to throw NPE");
} catch (NullPointerException e) {
// good
}
try {
// Check that a NULL destination throws NPE
UNSAFE.copySwapMemory(null, buf, null, 0, 16, 2);
throw new RuntimeException("copySwapMemory failed to throw NPE");
} catch (NullPointerException e) {
// good
}
try { try {
// Check that a reference array destination throws IAE // Check that a reference array destination throws IAE
UNSAFE.copySwapMemory(null, buf, new Object[16], UNSAFE.arrayBaseOffset(Object[].class), 16, 8); UNSAFE.copySwapMemory(null, buf, new Object[16], UNSAFE.arrayBaseOffset(Object[].class), 16, 8);
@ -653,59 +148,4 @@ public class CopySwap {
CopySwap cs = new CopySwap(); CopySwap cs = new CopySwap();
cs.test(); cs.test();
} }
/**
* Helper class to represent a "pointer" - either a heap array or
* a pointer to a native buffer.
*
* In the case of a native pointer, the Object is null and the offset is
* the absolute address of the native buffer.
*
* In the case of a heap object, the Object is a primitive array, and
* the offset will be set to the base offset to the first element, meaning
* the object and the offset together form a double-register pointer.
*/
static class GenericPointer {
private final Object o;
private final long offset;
private GenericPointer(Object o, long offset) {
this.o = o;
this.offset = offset;
}
public String toString() {
return "GenericPointer(o={" + o + "}, offset=0x" + Long.toHexString(offset) + ")";
}
public boolean equals(Object other) {
if (!(other instanceof GenericPointer)) {
return false;
}
GenericPointer otherp = (GenericPointer)other;
return o == otherp.o && offset == otherp.offset;
}
GenericPointer(Object o) {
this(o, UNSAFE.arrayBaseOffset(o.getClass()));
}
GenericPointer(long offset) {
this(null, offset);
}
public boolean isOnHeap() {
return o != null;
}
public Object getObject() {
return o;
}
public long getOffset() {
return offset;
}
}
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,7 @@
/* /*
* @test * @test
* @summary Unit test for sun.net.idn.Punycode * @summary Unit test for sun.net.idn.Punycode
* @bug 4737170 * @bug 4737170 8060097
* @modules java.base/sun.net.idn java.base/sun.text.normalizer * @modules java.base/sun.net.idn java.base/sun.text.normalizer
* @library . * @library .
* @compile -XDignore.symbol.file TestStringPrep.java NFS4StringPrep.java * @compile -XDignore.symbol.file TestStringPrep.java NFS4StringPrep.java
@ -41,6 +41,7 @@
import java.text.ParseException; import java.text.ParseException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Locale;
import sun.net.idn.StringPrep; import sun.net.idn.StringPrep;
import sun.text.normalizer.UCharacterIterator; import sun.text.normalizer.UCharacterIterator;
@ -209,7 +210,7 @@ public class TestStringPrep {
src = "THISISATEST"; src = "THISISATEST";
byte[] dest = NFS4StringPrep.cs_prepare(src.getBytes("UTF-8"), false); byte[] dest = NFS4StringPrep.cs_prepare(src.getBytes("UTF-8"), false);
String destStr = new String(dest, "UTF-8"); String destStr = new String(dest, "UTF-8");
if(!src.toLowerCase().equals(destStr)){ if(!src.toLowerCase(Locale.ROOT).equals(destStr)){
fail("Did not get expected output. Expected: "+ prettify(src)+ fail("Did not get expected output. Expected: "+ prettify(src)+
" Got: " + prettify(destStr)); " Got: " + prettify(destStr));
} }
@ -275,7 +276,7 @@ public class TestStringPrep {
private static String hex(char ch) { private static String hex(char ch) {
StringBuffer result = new StringBuffer(); StringBuffer result = new StringBuffer();
String foo = Integer.toString(ch,16).toUpperCase(); String foo = Integer.toString(ch,16).toUpperCase(Locale.ROOT);
for (int i = foo.length(); i < 4; ++i) { for (int i = foo.length(); i < 4; ++i) {
result.append('0'); result.append('0');
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -21,55 +21,52 @@
* questions. * questions.
*/ */
/**
* @test
* @bug 8076359 8133151
* @summary Test for jdk.security.provider.preferred security property
* @requires os.name == "SunOS"
* @run main/othervm PreferredProviderNegativeTest preJCESet AES:OracleUcrypto false
* @run main/othervm PreferredProviderNegativeTest preJCESet AES:SunNegative true
* @run main/othervm PreferredProviderNegativeTest afterJCESet AES:SunJGSS
* @run main/othervm PreferredProviderNegativeTest afterJCESet AES:SunECNegative
* @run main/othervm PreferredProviderNegativeTest invalidAlg AESNegative:SunJCE
*/
import java.security.Security; import java.security.Security;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException; import javax.crypto.NoSuchPaddingException;
/**
* @test
* @bug 8076359 8133151 8150512
* @summary Test for jdk.security.provider.preferred security property
* @run main/othervm PreferredProviderNegativeTest preSet AES false
* @run main/othervm PreferredProviderNegativeTest preSet AES:SunNegative true
* @run main/othervm PreferredProviderNegativeTest afterSet AES:SunJGSS
* @run main/othervm PreferredProviderNegativeTest afterSet AES:SunECNegative
* @run main/othervm PreferredProviderNegativeTest invalidAlg AESInvalid:SunJCE
*/
public class PreferredProviderNegativeTest { public class PreferredProviderNegativeTest {
static final String SEC_PREF_PROP = "jdk.security.provider.preferred";
/* /*
* Test security property could be set by valid and invalid provider * Test security property could be set by valid and invalid provider
* before JCE was loaded * before JCE was loaded
*/ */
public static void preJCESet(String value, boolean negativeProvider) public static void preJCESet(String value, boolean negativeProvider)
throws NoSuchAlgorithmException, NoSuchPaddingException { throws NoSuchAlgorithmException, NoSuchPaddingException {
Security.setProperty("jdk.security.provider.preferred", value);
if (!Security.getProperty("jdk.security.provider.preferred") Security.setProperty(SEC_PREF_PROP, value);
.equals(value)) {
throw new RuntimeException( if (!Security.getProperty(SEC_PREF_PROP).equals(value)) {
"Test Failed:The property wasn't set"); throw new RuntimeException("Test Failed:The property wasn't set");
} }
String[] arrays = value.split(":"); String[] arrays = value.split(":");
Cipher cipher = Cipher.getInstance(arrays[0]); Cipher cipher = Cipher.getInstance(arrays[0]);
if (negativeProvider) { if (negativeProvider) {
if (cipher.getProvider().getName().equals(arrays[1])) { if (cipher.getProvider().getName().equals(arrays[1])) {
throw new RuntimeException( throw new RuntimeException(
"Test Failed:The provider shouldn't be set"); "Test Failed:The provider shouldn't be set.");
} }
} else { } else {
if (!cipher.getProvider().getName().equals(arrays[1])) { if (!cipher.getProvider().getName().equals(arrays[1])) {
throw new RuntimeException( throw new RuntimeException("Test Faild:The provider could be "
"Test Faild:The provider could be set " + "set by valid provider.");
+ "by valid provider ");
} }
} }
System.out.println("Test Pass"); System.out.println("Test Pass.");
} }
/* /*
@ -81,10 +78,10 @@ public class PreferredProviderNegativeTest {
String[] arrays = value.split(":"); String[] arrays = value.split(":");
Cipher cipher = Cipher.getInstance(arrays[0]); Cipher cipher = Cipher.getInstance(arrays[0]);
Security.setProperty("jdk.security.provider.preferred", value); Security.setProperty(SEC_PREF_PROP, value);
if (!cipher.getProvider().getName().equals("SunJCE")) { if (!cipher.getProvider().getName().equals("SunJCE")) {
throw new RuntimeException( throw new RuntimeException("Test Failed:The security property can't"
"Test Failed:The security property can't be updated after JCE load."); + " be updated after JCE load.");
} }
System.out.println("Test Pass"); System.out.println("Test Pass");
} }
@ -94,10 +91,11 @@ public class PreferredProviderNegativeTest {
String[] arrays = value.split(":"); String[] arrays = value.split(":");
try { try {
Security.setProperty("jdk.security.provider.preferred", value); Security.setProperty(SEC_PREF_PROP, value);
Cipher.getInstance(arrays[0]); Cipher.getInstance(arrays[0]);
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
System.out.println("Test Pass:Got NoSuchAlgorithmException as expired"); System.out.println(
"Test Pass:Got NoSuchAlgorithmException as expired");
return; return;
} }
throw new RuntimeException( throw new RuntimeException(
@ -106,15 +104,25 @@ public class PreferredProviderNegativeTest {
public static void main(String[] args) public static void main(String[] args)
throws NoSuchAlgorithmException, NoSuchPaddingException { throws NoSuchAlgorithmException, NoSuchPaddingException {
boolean negativeProvider;
if (args.length >= 2) { if (args.length >= 2) {
switch (args[0]) { switch (args[0]) {
case "preJCESet": case "preSet":
negativeProvider = Boolean.valueOf(args[2]); boolean negativeProvider = Boolean.valueOf(args[2]);
PreferredProviderNegativeTest.preJCESet(args[1], negativeProvider); boolean solaris = System.getProperty("os.name")
.toLowerCase().contains("sun");
String value = args[1];
if (args[1].split(":").length < 2) {
if (solaris) {
value += ":OracleUcrypto";
} else {
value += ":SunJCE";
}
}
PreferredProviderNegativeTest.preJCESet(
value, negativeProvider);
break; break;
case "afterJCESet": case "afterSet":
PreferredProviderNegativeTest.afterJCESet(args[1]); PreferredProviderNegativeTest.afterJCESet(args[1]);
break; break;
case "invalidAlg": case "invalidAlg":
@ -127,4 +135,3 @@ public class PreferredProviderNegativeTest {
} }
} }
} }

@ -21,97 +21,131 @@
* questions. * questions.
*/ */
/**
* @test
* @bug 8076359 8133151 8145344
* @summary Test the value for new jdk.security.provider.preferred security property
* @requires os.name == "SunOS"
*/
import java.security.KeyFactory;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.Security; import java.security.Security;
import java.security.Provider;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException; import javax.crypto.NoSuchPaddingException;
/**
* @test
* @bug 8076359 8133151 8145344 8150512
* @summary Test the value for new jdk.security.provider.preferred
* security property
*/
public class PreferredProviderTest { public class PreferredProviderTest {
private static final List<DataTuple> SPARC_DATA = Arrays.asList( public void RunTest(String type, String os)
new DataTuple("SHA1", "SUN"), new DataTuple("SHA-1", "SUN"),
new DataTuple("SHA-224", "SUN"), new DataTuple("SHA-256", "SUN"),
new DataTuple("SHA-384", "SUN"), new DataTuple("SHA-512", "SUN"));
private static final List<DataTuple> X86_DATA = Arrays
.asList(new DataTuple("RSA", "SunRsaSign"));
public void RunTest(String type)
throws NoSuchAlgorithmException, NoSuchPaddingException { throws NoSuchAlgorithmException, NoSuchPaddingException {
String preferredProvider = Security
.getProperty("jdk.security.provider.preferred");
String actualProvider = null; String actualProvider = null;
if (type.equals("sparcv9")) { boolean solaris = os.contains("sun");
if (!preferredProvider.equals( String preferredProp
"AES:SunJCE, SHA1:SUN, SHA-224:SUN, SHA-256:SUN, SHA-384:SUN, SHA-512:SUN")) { = "AES/GCM/NoPadding:SunJCE, MessageDigest.SHA-256:SUN";
throw new RuntimeException( System.out.printf("%nExecuting test for the platform '%s'%n", os);
"Test Failed: wrong jdk.security.provider.preferred " if (!solaris) {
+ "value on solaris-sparcv9"); //For other platform it will try to set the preferred algorithm and
} //Provider and verify the usage of it.
for (DataTuple dataTuple : SPARC_DATA) { Security.setProperty(
MessageDigest md = MessageDigest "jdk.security.provider.preferred", preferredProp);
.getInstance(dataTuple.algorithm); verifyPreferredProviderProperty(os, type, preferredProp);
actualProvider = md.getProvider().getName();
if (!actualProvider.equals(dataTuple.provider)) { verifyDigestProvider(os, type, Arrays.asList(
throw new RuntimeException(String.format( new DataTuple("SHA-256", "SUN")));
"Test Failed:Got wrong "
+ "provider from Solaris-sparcv9 platform,"
+ "Expected Provider: %s, Returned Provider: %s",
dataTuple.provider, actualProvider));
}
}
} else if (type.equals("amd64")) {
if (!preferredProvider.equals("AES:SunJCE, RSA:SunRsaSign")) {
throw new RuntimeException(
"Test Failed: wrong jdk.security.provider.preferred "
+ "value on solaris-x86");
}
for (DataTuple dataTuple : X86_DATA) {
KeyFactory keyFactory = KeyFactory
.getInstance(dataTuple.algorithm);
actualProvider = keyFactory.getProvider().getName();
if (!actualProvider.equals(dataTuple.provider)) {
throw new RuntimeException(String.format(
"Test Failed:Got wrong "
+ "provider from Solaris-x86 platform,"
+ "Expected Provider: %s, Returned Provider: %s",
dataTuple.provider, actualProvider));
}
}
} else { } else {
throw new RuntimeException("Test Failed: wrong platform value"); //For solaris the preferred algorithm/provider is already set in
//java.security file which will be verified.
switch (type) {
case "sparcv9":
preferredProp = "AES:SunJCE, SHA1:SUN, SHA-224:SUN,"
+ " SHA-256:SUN, SHA-384:SUN, SHA-512:SUN";
verifyPreferredProviderProperty(os, type, preferredProp);
verifyDigestProvider(os, type, Arrays.asList(
new DataTuple("SHA1", "SUN"),
new DataTuple("SHA-1", "SUN"),
new DataTuple("SHA-224", "SUN"),
new DataTuple("SHA-256", "SUN"),
new DataTuple("SHA-384", "SUN"),
new DataTuple("SHA-512", "SUN")));
break;
case "amd64":
preferredProp = "AES:SunJCE, RSA:SunRsaSign";
verifyPreferredProviderProperty(os, type, preferredProp);
verifyKeyFactoryProvider(os, type, Arrays.asList(
new DataTuple("RSA", "SunRsaSign")));
break;
}
verifyDigestProvider(os, type, Arrays.asList(
new DataTuple("MD5", "OracleUcrypto")));
} }
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
actualProvider = cipher.getProvider().getName(); actualProvider = cipher.getProvider().getName();
if (!actualProvider.equals("SunJCE")) { if (!actualProvider.equals("SunJCE")) {
throw new RuntimeException(String.format( throw new RuntimeException(String.format("Test Failed:Got wrong "
"Test Failed:Got wrong provider from Solaris-%s platform, " + "provider from %s-%s platform, Expected Provider: SunJCE,"
+ "Expected Provider: SunJCE, Returned Provider: %s", + " Returned Provider: %s", os, type, actualProvider));
type, actualProvider));
} }
}
MessageDigest md = MessageDigest.getInstance("MD5"); private static void verifyPreferredProviderProperty(String os, String arch,
actualProvider = md.getProvider().getName(); String preferred) {
if (!actualProvider.equals("OracleUcrypto")) { String preferredProvider
= Security.getProperty("jdk.security.provider.preferred");
if (!preferredProvider.equals(preferred)) {
throw new RuntimeException(String.format( throw new RuntimeException(String.format(
"Test Failed:Got wrong provider from Solaris-%s platform," "Test Failed: wrong jdk.security.provider.preferred value "
+ "Expected Provider: OracleUcrypto, Returned Provider: %s", + "on %s-%s", os, arch));
type, actualProvider)); }
System.out.println(
"Preferred provider security property verification complete.");
}
private static void verifyDigestProvider(String os, String arch,
List<DataTuple> algoProviders) throws NoSuchAlgorithmException {
for (DataTuple dataTuple : algoProviders) {
System.out.printf(
"Verifying MessageDigest for '%s'%n", dataTuple.algorithm);
MessageDigest md = MessageDigest.getInstance(dataTuple.algorithm);
matchProvider(md.getProvider(), dataTuple.provider,
dataTuple.algorithm, os, arch);
}
System.out.println(
"Preferred MessageDigest algorithm verification successful.");
}
private static void verifyKeyFactoryProvider(String os, String arch,
List<DataTuple> algoProviders) throws NoSuchAlgorithmException {
for (DataTuple dataTuple : algoProviders) {
System.out.printf(
"Verifying KeyFactory for '%s'%n", dataTuple.algorithm);
KeyFactory kf = KeyFactory.getInstance(dataTuple.algorithm);
matchProvider(kf.getProvider(), dataTuple.provider,
dataTuple.algorithm, os, arch);
}
System.out.println(
"Preferred KeyFactory algorithm verification successful.");
}
private static void matchProvider(Provider provider, String expected,
String algo, String os, String arch) {
if (!provider.getName().equals(expected)) {
throw new RuntimeException(String.format(
"Test Failed:Got wrong provider from %s-%s platform, "
+ "for algorithm %s. Expected Provider: %s,"
+ " Returned Provider: %s", os, arch, algo,
expected, provider.getName()));
} }
} }
private static class DataTuple { private static class DataTuple {
private final String provider; private final String provider;
private final String algorithm; private final String algorithm;
@ -123,10 +157,9 @@ public class PreferredProviderTest {
public static void main(String[] args) public static void main(String[] args)
throws NoSuchAlgorithmException, NoSuchPaddingException { throws NoSuchAlgorithmException, NoSuchPaddingException {
String os = System.getProperty("os.name").toLowerCase();
String arch = System.getProperty("os.arch"); String arch = System.getProperty("os.arch").toLowerCase();
PreferredProviderTest pp = new PreferredProviderTest(); PreferredProviderTest pp = new PreferredProviderTest();
pp.RunTest(arch); pp.RunTest(arch, os);
} }
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -24,6 +24,7 @@
/* /*
* @test * @test
* @bug 6844193 * @bug 6844193
* @key intermittent
* @compile -XDignore.symbol.file MaxRetries.java * @compile -XDignore.symbol.file MaxRetries.java
* @run main/othervm/timeout=300 MaxRetries * @run main/othervm/timeout=300 MaxRetries
* @summary support max_retries in krb5.conf * @summary support max_retries in krb5.conf

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -24,6 +24,7 @@
/* /*
* @test * @test
* @bug 7162687 * @bug 7162687
* @key intermittent
* @summary enhance KDC server availability detection * @summary enhance KDC server availability detection
* @compile -XDignore.symbol.file Unreachable.java * @compile -XDignore.symbol.file Unreachable.java
* @run main/othervm/timeout=10 Unreachable * @run main/othervm/timeout=10 Unreachable

@ -32,6 +32,7 @@ import java.security.interfaces.RSAPrivateCrtKey;
/* /*
* @test * @test
* @bug 8023546 * @bug 8023546
* @key intermittent
* @modules java.base/sun.security.x509 * @modules java.base/sun.security.x509
* java.base/sun.security.tools.keytool * java.base/sun.security.tools.keytool
* @summary sun/security/mscapi/ShortRSAKey1024.sh fails intermittently * @summary sun/security/mscapi/ShortRSAKey1024.sh fails intermittently

@ -0,0 +1,183 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
/*
* @test
* @bug 8149169
* @summary Test for BufferOverflowException during read from SSLSocket when
* large packet is coming from server after server initiated handshake
* @run main/othervm LargePacketAfterHandshakeTest
*/
public class LargePacketAfterHandshakeTest {
static String pathToStores = "../../../../javax/net/ssl/etc";
static String keyStoreFile = "keystore";
static String trustStoreFile = "truststore";
static String passwd = "passphrase";
volatile static int serverport = -1;
volatile static boolean serverReady = false;
volatile static boolean clientDone = false;
volatile static Exception serverException = null;
public static void runServer() {
try {
System.out.println("Server: Started server thread.");
SSLServerSocketFactory ssf =
(SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
SSLServerSocket s = (SSLServerSocket)ssf.createServerSocket(0);
serverport = s.getLocalPort();
System.out.println("Server: Started, listening on port " +
serverport + ".");
serverReady = true;
SSLSocket c = (SSLSocket)s.accept();
s.close();
System.out.println(
"Server: Accepted client connection and closed server socket.");
BufferedReader r = new BufferedReader(
new InputStreamReader(c.getInputStream()));
BufferedWriter w = new BufferedWriter(
new OutputStreamWriter(c.getOutputStream()));
String echostring = r.readLine();
System.out.println("Server: Read " + echostring.length() +
" chars of input data.");
c.startHandshake();
System.out.println("Server: Kicked new handshake.");
w.write(echostring);
w.newLine();
w.flush();
System.out.println("Server: Echoed " + echostring.length() +
" chars of input data.");
while (!clientDone) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
System.out.println("Server: Caught InterruptedException.");
}
}
r.close();
w.close();
c.close();
System.out.println(
"Server: Closed streams and client socket, exiting.");
} catch (Exception e) {
System.out.println("Server: Caught Exception.");
e.printStackTrace();
serverReady = true;
serverException = e;
}
}
public static void runClient() throws IOException {
try {
SSLSocketFactory f =
(SSLSocketFactory)SSLSocketFactory.getDefault();
System.out.println("Client: Initialized.");
while (!serverReady) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
System.out.println("Client: Caught InterruptedException.");
}
}
SSLSocket c = (SSLSocket)f.createSocket("localhost", serverport);
BufferedWriter w = new BufferedWriter(
new OutputStreamWriter(c.getOutputStream()));
BufferedReader r = new BufferedReader(
new InputStreamReader(c.getInputStream()));
System.out.println("Client: Connected.");
String echoPattern = "Otto";
StringBuilder echoBuilder =
new StringBuilder(4500 + echoPattern.length());
while (echoBuilder.length() < 4500) {
echoBuilder.append(echoPattern);
}
String echostring = echoBuilder.toString();
w.write(echostring);
w.newLine();
w.flush();
System.out.println("Client: Sent " + echostring.length() +
" chars of data.");
String echoresponse = r.readLine();
clientDone = true;
System.out.println("Client: Read " + echoresponse.length() +
" chars of data.");
w.close();
r.close();
c.close();
System.out.println("Client: Closed streams and socket, exiting.");
} catch (IOException e) {
System.out.println("Client: Caught Exception.");
e.printStackTrace();
clientDone = true;
throw e;
}
}
public static void main(String[] args) throws Exception {
String keyFilename = System.getProperty("test.src", "./") + "/" +
pathToStores + "/" + keyStoreFile;
String trustFilename = System.getProperty("test.src", "./") + "/" +
pathToStores + "/" + trustStoreFile;
System.setProperty("javax.net.ssl.keyStore", keyFilename);
System.setProperty("javax.net.ssl.keyStorePassword", passwd);
System.setProperty("javax.net.ssl.trustStore", trustFilename);
System.setProperty("javax.net.ssl.trustStorePassword", passwd);
Thread serverThread = new Thread() {
@Override
public void run() {
runServer();
}
};
serverThread.start();
runClient();
while (serverThread.isAlive()) {
try {
serverThread.join();
} catch (InterruptedException e) {
System.out.println("Main: Caught InterruptedException " +
" waiting for server Thread.");
}
}
if (serverException != null) {
throw serverException;
}
}
}

@ -21,26 +21,18 @@
* questions. * questions.
*/ */
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Layer;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Stream;
import jdk.tools.jlink.plugin.Plugin; import jdk.tools.jlink.plugin.Plugin;
import jdk.tools.jlink.plugin.PluginException;
import jdk.tools.jlink.internal.PluginRepository; import jdk.tools.jlink.internal.PluginRepository;
import jdk.tools.jlink.internal.TaskHelper;
import jdk.tools.jlink.internal.plugins.PluginsResourceBundle;
import tests.Helper; import tests.Helper;
import tests.JImageGenerator; import tests.JImageGenerator;
import tests.JImageValidator; import tests.JImageValidator;
import tests.Result;
/* /*
* @test * @test
@ -50,6 +42,7 @@ import tests.JImageValidator;
* @modules java.base/jdk.internal.jimage * @modules java.base/jdk.internal.jimage
* jdk.jdeps/com.sun.tools.classfile * jdk.jdeps/com.sun.tools.classfile
* jdk.jlink/jdk.tools.jlink.internal * jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.internal.plugins
* jdk.jlink/jdk.tools.jmod * jdk.jlink/jdk.tools.jmod
* jdk.jlink/jdk.tools.jimage * jdk.jlink/jdk.tools.jimage
* jdk.compiler * jdk.compiler
@ -65,6 +58,7 @@ public class IncludeLocalesPluginTest {
private final static int EXPECTED_LOCATIONS = 1; private final static int EXPECTED_LOCATIONS = 1;
private final static int UNEXPECTED_PATHS = 2; private final static int UNEXPECTED_PATHS = 2;
private final static int AVAILABLE_LOCALES = 3; private final static int AVAILABLE_LOCALES = 3;
private final static int ERROR_MESSAGE = 4;
private final static Object[][] testData = { private final static Object[][] testData = {
// without --include-locales option: should include all locales // without --include-locales option: should include all locales
@ -144,6 +138,7 @@ public class IncludeLocalesPluginTest {
"yav_CM yo yo_BJ yo_NG zgh zgh_MA zh zh_CN zh_CN_#Hans zh_HK " + "yav_CM yo yo_BJ yo_NG zgh zgh_MA zh zh_CN zh_CN_#Hans zh_HK " +
"zh_HK_#Hans zh_HK_#Hant zh_MO_#Hans zh_MO_#Hant zh_SG zh_SG_#Hans " + "zh_HK_#Hans zh_HK_#Hant zh_MO_#Hans zh_MO_#Hant zh_SG zh_SG_#Hans " +
"zh_TW zh_TW_#Hant zh__#Hans zh__#Hant zu zu_ZA", "zh_TW zh_TW_#Hant zh__#Hans zh__#Hant zu zu_ZA",
"",
}, },
// All English/Japanese locales // All English/Japanese locales
@ -173,6 +168,7 @@ public class IncludeLocalesPluginTest {
"en_PW en_RW en_SB en_SC en_SD en_SG en_SH en_SL en_SS en_SX en_SZ " + "en_PW en_RW en_SB en_SC en_SD en_SG en_SH en_SL en_SS en_SX en_SZ " +
"en_TC en_TK en_TO en_TT en_TV en_TZ en_UG en_UM en_US en_US_POSIX " + "en_TC en_TK en_TO en_TT en_TV en_TZ en_UG en_UM en_US en_US_POSIX " +
"en_VC en_VG en_VI en_VU en_WS en_ZA en_ZM en_ZW ja ja_JP ja_JP_JP_#u-ca-japanese", "en_VC en_VG en_VI en_VU en_WS en_ZA en_ZM en_ZW ja ja_JP ja_JP_JP_#u-ca-japanese",
"",
}, },
// All locales in India // All locales in India
@ -201,6 +197,7 @@ public class IncludeLocalesPluginTest {
"/jdk.localedata/sun/text/resources/cldr/ext/FormatData_zh.class"), "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_zh.class"),
" as_IN bn_IN bo_IN brx_IN en en_IN en_US en_US_POSIX gu_IN hi_IN kn_IN " + " as_IN bn_IN bo_IN brx_IN en en_IN en_US en_US_POSIX gu_IN hi_IN kn_IN " +
"kok_IN ks_IN_#Arab ml_IN mr_IN ne_IN or_IN pa_IN_#Guru ta_IN te_IN ur_IN", "kok_IN ks_IN_#Arab ml_IN mr_IN ne_IN or_IN pa_IN_#Guru ta_IN te_IN ur_IN",
"",
}, },
// Thai // Thai
@ -220,6 +217,7 @@ public class IncludeLocalesPluginTest {
"/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class",
"/jdk.localedata/sun/text/resources/cldr/ext/FormatData_zh.class"), "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_zh.class"),
" en en_US en_US_POSIX th th_TH th_TH_TH_#u-nu-thai", " en en_US en_US_POSIX th th_TH th_TH_TH_#u-nu-thai",
"",
}, },
// Hong Kong // Hong Kong
@ -242,6 +240,7 @@ public class IncludeLocalesPluginTest {
"/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class",
"/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class"), "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class"),
" en en_US en_US_POSIX zh_HK zh_HK_#Hans zh_HK_#Hant", " en en_US en_US_POSIX zh_HK zh_HK_#Hans zh_HK_#Hant",
"",
}, },
// Norwegian // Norwegian
@ -265,6 +264,7 @@ public class IncludeLocalesPluginTest {
"/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class",
"/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class"), "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class"),
" en en_US en_US_POSIX nb nb_NO nb_SJ nn nn_NO no no_NO no_NO_NY", " en en_US en_US_POSIX nb nb_NO nb_SJ nn nn_NO no no_NO no_NO_NY",
"",
}, },
// Hebrew/Indonesian/Yiddish // Hebrew/Indonesian/Yiddish
@ -290,6 +290,25 @@ public class IncludeLocalesPluginTest {
"/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class",
"/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class"), "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class"),
" en en_US en_US_POSIX in in_ID iw iw_IL ji ji_001", " en en_US en_US_POSIX in in_ID iw iw_IL ji ji_001",
"",
},
// Error case: No matching locales
{"--include-locales=xyz",
null,
null,
null,
new PluginException(
PluginsResourceBundle.getMessage("include-locales.nomatchinglocales"))
.toString(),
},
// Error case: Invalid argument
{"--include-locales=zh_HK",
null,
null,
null,
"range=zh_hk",
}, },
}; };
@ -304,20 +323,28 @@ public class IncludeLocalesPluginTest {
for (Object[] data : testData) { for (Object[] data : testData) {
// create image for each test data // create image for each test data
Path image = JImageGenerator.getJLinkTask() Result result = JImageGenerator.getJLinkTask()
.modulePath(helper.defaultModulePath()) .modulePath(helper.defaultModulePath())
.output(helper.createNewImageDir(moduleName)) .output(helper.createNewImageDir(moduleName))
.addMods("jdk.localedata") .addMods("jdk.localedata")
.option((String)data[INCLUDE_LOCALES_OPTION]) .option((String)data[INCLUDE_LOCALES_OPTION])
.call().assertSuccess(); .call();
// test locale data entries String errorMsg = (String)data[ERROR_MESSAGE];
testLocaleDataEntries(image, if (errorMsg.isEmpty()) {
(List<String>)data[EXPECTED_LOCATIONS], Path image = result.assertSuccess();
(List<String>)data[UNEXPECTED_PATHS]);
// test available locales // test locale data entries
testAvailableLocales(image, (String)data[AVAILABLE_LOCALES]); testLocaleDataEntries(image,
(List<String>)data[EXPECTED_LOCATIONS],
(List<String>)data[UNEXPECTED_PATHS]);
// test available locales
testAvailableLocales(image, (String)data[AVAILABLE_LOCALES]);
} else {
result.assertFailure(new TaskHelper(TaskHelper.JLINK_BUNDLE)
.getMessage("error.prefix") + " " +errorMsg);
}
} }
} }