From 317553031c74d47019b9aefcfaf18b0e2cc4526b Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Mon, 19 Oct 2015 17:52:39 +0300 Subject: [PATCH 01/31] 8139881: Exclude java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java from execution Reviewed-by: kvn --- .../java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java b/jdk/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java index 3a97456e1a4..6f4ad86a280 100644 --- a/jdk/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java +++ b/jdk/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java @@ -23,6 +23,7 @@ /* * @test LFSingleThreadCachingTest + * @ignore 8129523 * @bug 8046703 * @key randomness * @summary Test verifies that lambda forms are cached when run with single thread From cdd7249f6e1537f9c2b9e26d6a1a80f91e090356 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Fri, 30 Oct 2015 11:12:20 -0400 Subject: [PATCH 02/31] 8139390: Very long classname in jimage causes SIGSEGV Correct issues with ImageNativeSubstrate and JImageReadTest Reviewed-by: mchung --- .../native/libjimage/ImageNativeSubstrate.cpp | 86 +++++++++++++++---- .../share/native/libjimage/jimage.cpp | 29 +++++-- .../jdk/internal/jimage/JImageReadTest.java | 30 ++++++- 3 files changed, 117 insertions(+), 28 deletions(-) diff --git a/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp b/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp index d2217e4fe62..0f803cb4fa9 100644 --- a/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp +++ b/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp @@ -26,8 +26,7 @@ #include #include "jni.h" -#include "jni_util.h" -#include "jdk_util.h" + #include "endian.hpp" #include "imageDecompressor.hpp" #include "imageFile.hpp" @@ -39,6 +38,17 @@ extern bool MemoryMapImage; +///////////////////////////////////////////////////////////////////////////// + +// Static function for primitive throw since libjimage is not linked with libjava +static void JNICALL ThrowByName(JNIEnv *env, const char *name, const char *msg) +{ + jclass cls = (env)->FindClass(name); + + if (cls != 0) /* Otherwise an exception has already been thrown */ + (env)->ThrowNew(cls, msg); +} + // jdk.internal.jimage ///////////////////////////////////////////////////////// // Java entry to open an image file for sharing. @@ -446,6 +456,23 @@ JNIEXPORT jlong JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Fi jlong size = 0; jlong ret = 0; + if (moduleName == NULL) { + ThrowByName(env, "java/lang/NullPointerException", "moduleName"); + return 0; + } + if (version == NULL) { + ThrowByName(env, "java/lang/NullPointerException", "version"); + return 0; + } + if (path == NULL) { + ThrowByName(env, "java/lang/NullPointerException", "path"); + return 0; + } + if (output_size == NULL) { + ThrowByName(env, "java/lang/NullPointerException", "size"); + return 0; + } + do { native_module = env->GetStringUTFChars(moduleName, NULL); if (native_module == NULL) @@ -529,25 +556,47 @@ static bool resourceVisitor(JImageFile* image, // Store if there is room in the array // Concatenate to get full path char fullpath[IMAGE_MAX_PATH]; - fullpath[0] = '\0'; - if (*module != '\0') { - strncpy(fullpath, "/", IMAGE_MAX_PATH - 1); - strncat(fullpath, module, IMAGE_MAX_PATH - 1); - strncat(fullpath, "/", IMAGE_MAX_PATH - 1); + size_t moduleLen = strlen(module); + size_t packageLen = strlen(package); + size_t nameLen = strlen(name); + size_t extLen = strlen(extension); + size_t index; + + if (1 + moduleLen + 1 + packageLen + 1 + nameLen + 1 + extLen + 1 > IMAGE_MAX_PATH) { + ThrowByName(env, "java/lang/InternalError", "concatenated name too long"); + return true; } - if (*package != '\0') { - strncat(fullpath, package, IMAGE_MAX_PATH - 1); - strncat(fullpath, "/", IMAGE_MAX_PATH - 1); + + index = 0; + if (moduleLen > 0) { + fullpath[index++] = '/'; + memcpy(&fullpath[index], module, moduleLen); + index += moduleLen; + fullpath[index++] = '/'; } - strncat(fullpath, name, IMAGE_MAX_PATH - 1); - if (*extension != '\0') { - strncat(fullpath, ".", IMAGE_MAX_PATH - 1); - strncat(fullpath, extension, IMAGE_MAX_PATH - 1); + if (packageLen > 0) { + memcpy(&fullpath[index], package, packageLen); + index += packageLen; + fullpath[index++] = '/'; } + memcpy(&fullpath[index], name, nameLen); + index += nameLen; + if (extLen > 0) { + fullpath[index++] = '.'; + memcpy(&fullpath[index], extension, extLen); + index += extLen; + } + fullpath[index++] = '\0'; + jobject str = env->NewStringUTF(fullpath); - JNU_CHECK_EXCEPTION_RETURN(env, true); + if (env->ExceptionCheck()) { + return true; + } + env->SetObjectArrayElement(vdata->array, vdata->size, str); - JNU_CHECK_EXCEPTION_RETURN(env, true); + if (env->ExceptionCheck()) { + return true; + } } vdata->size++; // always count so the total size is returned return true; @@ -584,7 +633,10 @@ JNIEXPORT jstring JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1 jstring module = NULL; native_package = env->GetStringUTFChars(package_name, NULL); - JNU_CHECK_EXCEPTION_RETURN(env, NULL); + if (env->ExceptionCheck()) { + return NULL; + } + native_module = JIMAGE_PackageToModule((JImageFile*) jimageHandle, native_package); if (native_module != NULL) { diff --git a/jdk/src/java.base/share/native/libjimage/jimage.cpp b/jdk/src/java.base/share/native/libjimage/jimage.cpp index cd09ffa2339..371cb1dc706 100644 --- a/jdk/src/java.base/share/native/libjimage/jimage.cpp +++ b/jdk/src/java.base/share/native/libjimage/jimage.cpp @@ -102,14 +102,29 @@ extern "C" const char* JIMAGE_PackageToModule(JImageFile* image, const char* pac extern "C" JImageLocationRef JIMAGE_FindResource(JImageFile* image, const char* module_name, const char* version, const char* name, jlong* size) { - ImageLocation location; - char fullpath[IMAGE_MAX_PATH]; - // Concatenate to get full path - strncpy(fullpath, "/", IMAGE_MAX_PATH - 1); - strncat(fullpath, module_name, IMAGE_MAX_PATH - 1); - strncat(fullpath, "/", IMAGE_MAX_PATH - 1); - strncat(fullpath, name, IMAGE_MAX_PATH - 1); + char fullpath[IMAGE_MAX_PATH]; + size_t moduleNameLen = strlen(module_name); + size_t nameLen = strlen(name); + size_t index; + + // TBD: assert(moduleNameLen > 0 && "module name must be non-empty"); + assert(nameLen > 0 && "name must non-empty"); + + // If the concatenated string is too long for the buffer, return not found + if (1 + moduleNameLen + 1 + nameLen + 1 > IMAGE_MAX_PATH) { + return 0L; + } + + index = 0; + fullpath[index++] = '/'; + memcpy(&fullpath[index], module_name, moduleNameLen); + index += moduleNameLen; + fullpath[index++] = '/'; + memcpy(&fullpath[index], name, nameLen); + index += nameLen; + fullpath[index++] = '\0'; + JImageLocationRef loc = (JImageLocationRef) ((ImageFileReader*) image)->find_location_index(fullpath, (u8*) size); return loc; diff --git a/jdk/test/jdk/internal/jimage/JImageReadTest.java b/jdk/test/jdk/internal/jimage/JImageReadTest.java index 910c35aec4a..82df8c83384 100644 --- a/jdk/test/jdk/internal/jimage/JImageReadTest.java +++ b/jdk/test/jdk/internal/jimage/JImageReadTest.java @@ -22,7 +22,9 @@ */ /* + * @test * @modules java.base/jdk.internal.jimage + * @run testng JImageReadTest * @summary Unit test for libjimage JIMAGE_Open/Read/Close */ @@ -57,8 +59,7 @@ public class JImageReadTest { {"java.base", "java/lang/String.class"}, {"java.base", "java/lang/Object.class"}, {"java.base", "sun/reflect/generics/tree/TypeArgument.class"}, - {"jdk.jdeps", "com/sun/tools/javap/StackMapWriter$StackMapBuilder.class"}, - {"jdk.hotspot.agent", "sa.properties"}, + {"java.base", "sun/net/www/content-types.properties"}, {"java.logging", "java/util/logging/Logger.class"}, {"java.base", "java/NOSUCHCLASS/yyy.class"}, // non-existent {"NOSUCHMODULE", "java/lang/Class.class"}, // non-existent @@ -165,8 +166,10 @@ public class JImageReadTest { int count = ImageNativeSubstrate.JIMAGE_Resources(jimageHandle, names); System.out.printf(" count: %d, a class: %s\n", count, names[0]); - Assert.assertTrue(max > 31000, - "missing entries, should be more than 31000, reported: " + count); + int minEntryCount = 16000; + Assert.assertTrue(max > minEntryCount, + "missing entries, should be more than " + minEntryCount + + ", reported: " + count); Assert.assertTrue(count == max, "unexpected count of entries, count: " + count + ", max: " + max); @@ -310,6 +313,7 @@ public class JImageReadTest { static boolean isMetaName(String name) { return name.startsWith("/modules") || name.startsWith("/packages") + || name.startsWith("META-INF/services") || name.equals("bootmodules.jdata"); } @@ -362,6 +366,24 @@ public class JImageReadTest { System.out.printf(" %s: %d names%n", fname, names.length); } + @Test + static void test5_nameTooLong() throws IOException { + long[] size = new long[1]; + String moduleName = "FictiousModuleName"; + String className = String.format("A%09999d", 1); + + long jimageHandle = ImageNativeSubstrate.JIMAGE_Open(imageFile); + Assert.assertTrue(jimageHandle != 0, "JIMAGE_Open failed: id: " + jimageHandle); + + long locationHandle = + ImageNativeSubstrate.JIMAGE_FindResource(jimageHandle, + moduleName, "9.0", className, size); + + Assert.assertEquals(0, locationHandle, "Too long name should have failed"); + + ImageNativeSubstrate.JIMAGE_Close(jimageHandle); + } + // main method to run standalone from jtreg @Test(enabled=false) From 638270935d3c48b079f423030a0d2da7ca240ae1 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Mon, 2 Nov 2015 14:57:04 +0100 Subject: [PATCH 03/31] 8140514: [TESTBUG] enable sun/security/pkcs11 tests on Linux/ppc64 Reviewed-by: wetmore --- jdk/test/sun/security/pkcs11/PKCS11Test.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/test/sun/security/pkcs11/PKCS11Test.java b/jdk/test/sun/security/pkcs11/PKCS11Test.java index 6ee011a294d..1e738601104 100644 --- a/jdk/test/sun/security/pkcs11/PKCS11Test.java +++ b/jdk/test/sun/security/pkcs11/PKCS11Test.java @@ -539,6 +539,7 @@ public abstract class PKCS11Test { osMap.put("Linux-amd64-64", new String[]{ "/usr/lib/x86_64-linux-gnu/", "/usr/lib/x86_64-linux-gnu/nss/", "/usr/lib64/"}); + osMap.put("Linux-ppc64-64", new String[]{"/usr/lib64/"}); osMap.put("Windows-x86-32", new String[]{ PKCS11_BASE + "/nss/lib/windows-i586/".replace('/', SEP)}); osMap.put("Windows-amd64-64", new String[]{ From 5710e3c7543e7effef4cea30bad8b66f3c31a627 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Mon, 2 Nov 2015 08:46:19 -0800 Subject: [PATCH 04/31] 8062006: Add a new locale data name "COMPAT" for java.locale.providers system property to reduce ambiguity Reviewed-by: okutsu --- .../java/util/spi/LocaleServiceProvider.java | 14 ++++---- .../provider/LocaleProviderAdapter.java | 4 +++ jdk/test/java/util/Locale/LocaleProviders.sh | 33 ++++++++++++------- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java b/jdk/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java index 582bbba95c8..a9bc8863ded 100644 --- a/jdk/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java +++ b/jdk/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java @@ -123,25 +123,27 @@ import java.util.Locale; *
    *
  • "CLDR": A provider based on Unicode Consortium's * CLDR Project. - *
  • "JRE": represents the locale sensitive services that is compatible - * with the prior JDK releases (same with JDK8's "JRE"). + *
  • "COMPAT": represents the locale sensitive services that is compatible + * with the prior JDK releases up to JDK8 (same as JDK8's "JRE"). *
  • "SPI": represents the locale sensitive services implementing the subclasses of * this {@code LocaleServiceProvider} class. *
  • "HOST": A provider that reflects the user's custom settings in the * underlying operating system. This provider may not be available, depending * on the Java Runtime Environment implementation. + *
  • "JRE": represents a synonym to "COMPAT". This name + * is deprecated and will be removed in the future release of JDK. *
*

* For example, if the following is specified in the property: *

- * java.locale.providers=SPI,CLDR,JRE
+ * java.locale.providers=SPI,CLDR,COMPAT
  * 
* the locale sensitive services in the SPI providers are looked up first. If the * desired locale sensitive service is not available, then the runtime looks for CLDR, - * JRE in that order. + * COMPAT in that order. *

- * The default order for looking up the preferred locale providers is "CLDR,JRE", - * so specifying "CLDR,JRE" is identical to the default behavior. Applications which + * The default order for looking up the preferred locale providers is "CLDR,COMPAT", + * so specifying "CLDR,COMPAT" is identical to the default behavior. Applications which * require implementations of the locale sensitive services must explicitly specify * "SPI" in order for the Java runtime to load them from the classpath. * diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java index 0844a701594..c17856ffe9a 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java @@ -124,6 +124,10 @@ public abstract class LocaleProviderAdapter { if (order != null && order.length() != 0) { String[] types = order.split(","); for (String type : types) { + type = type.trim().toUpperCase(Locale.ROOT); + if (type.equals("COMPAT")) { + type = "JRE"; + } try { Type aType = Type.valueOf(type.trim().toUpperCase(Locale.ROOT)); if (!typeList.contains(aType)) { diff --git a/jdk/test/java/util/Locale/LocaleProviders.sh b/jdk/test/java/util/Locale/LocaleProviders.sh index 5e1b79383f5..fb8043e21c3 100644 --- a/jdk/test/java/util/Locale/LocaleProviders.sh +++ b/jdk/test/java/util/Locale/LocaleProviders.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ # # @test # @bug 6336885 7196799 7197573 7198834 8000245 8000615 8001440 8008577 -# 8010666 8013086 8013233 8013903 8015960 8028771 +# 8010666 8013086 8013233 8013903 8015960 8028771 8062006 # @summary tests for "java.locale.providers" system property # @compile -XDignore.symbol.file LocaleProviders.java # @run shell/timeout=600 LocaleProviders.sh @@ -182,7 +182,7 @@ PARAM1=JRE if [ "${DEFLANG}" != "en" ] && [ "${DEFFMTLANG}" != "en" ]; then PARAM2=en PARAM3=US -elif [ "${DEFLANG}" != "ja" ] && [ "${DEFFMTLANG}" != "ja" ]; then +elif [ "${DEFLANG}" != "ja" ] && [ "${DEFFMTLANG}" != "ja" ]; then PARAM2=ja PARAM3=JP else @@ -200,6 +200,8 @@ PARAM2=en PARAM3=US SPICLASSES= runTest +PREFLIST=SPI,COMPAT +runTest # testing the order, variaton #1. This assumes en_GB DateFormat data are available both in JRE & CLDR METHODNAME=adapterTest @@ -209,6 +211,8 @@ PARAM2=en PARAM3=GB SPICLASSES= runTest +PREFLIST=CLDR,COMPAT +runTest # testing the order, variaton #2. This assumes en_GB DateFormat data are available both in JRE & CLDR METHODNAME=adapterTest @@ -218,6 +222,8 @@ PARAM2=en PARAM3=GB SPICLASSES= runTest +PREFLIST=COMPAT,CLDR +runTest # testing the order, variaton #3 for non-existent locale in JRE assuming "haw" is not in JRE. METHODNAME=adapterTest @@ -227,6 +233,8 @@ PARAM2=haw PARAM3= SPICLASSES= runTest +PREFLIST=COMPAT,CLDR +runTest # testing the order, variaton #4 for the bug 7196799. CLDR's "zh" data should be used in "zh_CN" METHODNAME=adapterTest @@ -275,6 +283,8 @@ PARAM2= PARAM3= SPICLASSES=${SPIDIR} runTest +PREFLIST=COMPAT +runTest # testing 8000615 fix. METHODNAME=tzNameTest @@ -284,6 +294,8 @@ PARAM2= PARAM3= SPICLASSES=${SPIDIR} runTest +PREFLIST=COMPAT +runTest # testing 8001440 fix. METHODNAME=bug8001440Test @@ -314,6 +326,8 @@ PARAM2=JP PARAM3= SPICLASSES=${SPIDIR} runTest +PREFLIST=COMPAT,SPI +runTest # testing 8013903 fix. (Windows only) METHODNAME=bug8013903Test @@ -323,12 +337,9 @@ PARAM2= PARAM3= SPICLASSES= runTest -METHODNAME=bug8013903Test PREFLIST=HOST -PARAM1= -PARAM2= -PARAM3= -SPICLASSES= +runTest +PREFLIST=HOST,COMPAT runTest # testing 8027289 fix, if the platform format default is zh_CN @@ -342,12 +353,10 @@ if [ "${DEFFMTLANG}" = "zh" ] && [ "${DEFFMTCTRY}" = "CN" ]; then PARAM3= SPICLASSES= runTest - METHODNAME=bug8027289Test + PREFLIST=COMPAT,HOST + runTest PREFLIST=HOST PARAM1=00A5 - PARAM2= - PARAM3= - SPICLASSES= runTest fi From dc711078d4f29a414c91750e222f82fabe5ca92e Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Wed, 23 Sep 2015 14:25:02 +0200 Subject: [PATCH 05/31] 8139727: Define ConstructorParameters annotation type for MXBeans Reviewed-by: alanb, mchung, dfuchs, abuckley, plevart, mr --- .../DefaultMXBeanMappingFactory.java | 58 ++++++---- .../management/ConstructorParameters.java | 76 +++++++++++++ .../classes/javax/management/MXBean.java | 42 ++++--- .../Introspector/AnnotationSecurityTest.java | 8 +- .../management/Introspector/Described.java | 4 +- .../management/Introspector/DescribedMX.java | 4 +- .../LegacyConstructorPropertiesTest.java | 106 ++++++++++++++++++ .../mxbean/AmbiguousConstructorTest.java | 18 ++- .../mxbean/ExceptionDiagnosisTest.java | 7 +- .../javax/management/mxbean/LeakTest.java | 3 +- .../javax/management/mxbean/MXBeanTest.java | 3 +- .../management/mxbean/PropertyNamesTest.java | 13 +-- .../javax/management/mxbean/TigerMXBean.java | 6 +- 13 files changed, 272 insertions(+), 76 deletions(-) create mode 100644 jdk/src/java.management/share/classes/javax/management/ConstructorParameters.java create mode 100644 jdk/test/javax/management/Introspector/LegacyConstructorPropertiesTest.java diff --git a/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java b/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java index 0b2835f9ee0..c322ed4f028 100644 --- a/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java +++ b/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java @@ -60,6 +60,7 @@ import java.util.WeakHashMap; import javax.management.JMX; import javax.management.ObjectName; +import javax.management.ConstructorParameters; import javax.management.openmbean.ArrayType; import javax.management.openmbean.CompositeData; import javax.management.openmbean.CompositeDataInvocationHandler; @@ -1132,8 +1133,8 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { } /** Builder for when the target class has a constructor that is - annotated with @ConstructorProperties so we can see the correspondence - to getters. */ + annotated with {@linkplain ConstructorParameters @ConstructorParameters} + or {@code @ConstructorProperties} so we can see the correspondence to getters. */ private static final class CompositeBuilderViaConstructor extends CompositeBuilder { @@ -1141,10 +1142,19 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { super(targetClass, itemNames); } - String applicable(Method[] getters) throws InvalidObjectException { - if (!JavaBeansAccessor.isAvailable()) - return "@ConstructorProperties annotation not available"; + private String[] getConstPropValues(Constructor ctr) { + // is constructor annotated by javax.management.ConstructorParameters ? + ConstructorParameters ctrProps = ctr.getAnnotation(ConstructorParameters.class); + if (ctrProps != null) { + return ctrProps.value(); + } else { + // try the legacy java.beans.ConstructorProperties annotation + String[] vals = JavaBeansAccessor.getConstructorPropertiesValue(ctr); + return vals; + } + } + String applicable(Method[] getters) throws InvalidObjectException { Class targetClass = getTargetClass(); Constructor[] constrs = targetClass.getConstructors(); @@ -1152,12 +1162,13 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { List> annotatedConstrList = newList(); for (Constructor constr : constrs) { if (Modifier.isPublic(constr.getModifiers()) - && JavaBeansAccessor.getConstructorPropertiesValue(constr) != null) + && getConstPropValues(constr) != null) annotatedConstrList.add(constr); } if (annotatedConstrList.isEmpty()) - return "no constructor has @ConstructorProperties annotation"; + return "no constructor has either @ConstructorParameters " + + "or @ConstructorProperties annotation"; annotatedConstructors = newList(); @@ -1181,13 +1192,17 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { // so we can test unambiguity. Set getterIndexSets = newSet(); for (Constructor constr : annotatedConstrList) { - String[] propertyNames = JavaBeansAccessor.getConstructorPropertiesValue(constr); + String annotationName = + constr.isAnnotationPresent(ConstructorParameters.class) ? + "@ConstructorParameters" : "@ConstructorProperties"; + + String[] propertyNames = getConstPropValues(constr); Type[] paramTypes = constr.getGenericParameterTypes(); if (paramTypes.length != propertyNames.length) { final String msg = "Number of constructor params does not match " + - "@ConstructorProperties annotation: " + constr; + annotationName + " annotation: " + constr; throw new InvalidObjectException(msg); } @@ -1200,7 +1215,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { String propertyName = propertyNames[i]; if (!getterMap.containsKey(propertyName)) { String msg = - "@ConstructorProperties includes name " + propertyName + + annotationName + " includes name " + propertyName + " which does not correspond to a property"; for (String getterName : getterMap.keySet()) { if (getterName.equalsIgnoreCase(propertyName)) { @@ -1215,7 +1230,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { paramIndexes[getterIndex] = i; if (present.get(getterIndex)) { final String msg = - "@ConstructorProperties contains property " + + annotationName + " contains property " + propertyName + " more than once: " + constr; throw new InvalidObjectException(msg); } @@ -1224,7 +1239,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { Type propertyType = getter.getGenericReturnType(); if (!propertyType.equals(paramTypes[i])) { final String msg = - "@ConstructorProperties gives property " + propertyName + + annotationName + " gives property " + propertyName + " of type " + propertyType + " for parameter " + " of type " + paramTypes[i] + ": " + constr; throw new InvalidObjectException(msg); @@ -1233,7 +1248,8 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { if (!getterIndexSets.add(present)) { final String msg = - "More than one constructor has a @ConstructorProperties " + + "More than one constructor has " + + "@ConstructorParameters or @ConstructorProperties " + "annotation with this set of names: " + Arrays.toString(propertyNames); throw new InvalidObjectException(msg); @@ -1252,10 +1268,10 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { * just the bigger constructor. * * The algorithm here is quadratic in the number of constructors - * with a @ConstructorProperties annotation. Typically this corresponds - * to the number of versions of the class there have been. Ten - * would already be a large number, so although it's probably - * possible to have an O(n lg n) algorithm it wouldn't be + * with a @ConstructorParameters or @ConstructructorProperties annotation. + * Typically this corresponds to the number of versions of the class + * there have been. Ten would already be a large number, so although + * it's probably possible to have an O(n lg n) algorithm it wouldn't be * worth the complexity. */ for (BitSet a : getterIndexSets) { @@ -1272,8 +1288,9 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { i = u.nextSetBit(i+1)) names.add(itemNames[i]); final String msg = - "Constructors with @ConstructorProperties annotation " + - " would be ambiguous for these items: " + + "Constructors with @ConstructorParameters or " + + "@ConstructorProperties annotation " + + "would be ambiguous for these items: " + names; throw new InvalidObjectException(msg); } @@ -1310,7 +1327,8 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { if (max == null) { final String msg = - "No constructor has a @ConstructorProperties for this set of " + + "No constructor has either @ConstructorParameters " + + "or @ConstructorProperties annotation for this set of " + "items: " + ct.keySet(); throw new InvalidObjectException(msg); } diff --git a/jdk/src/java.management/share/classes/javax/management/ConstructorParameters.java b/jdk/src/java.management/share/classes/javax/management/ConstructorParameters.java new file mode 100644 index 00000000000..d3d447e2a53 --- /dev/null +++ b/jdk/src/java.management/share/classes/javax/management/ConstructorParameters.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2006, 2015 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.management; + +import java.lang.annotation.*; +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +/** + *

+ * An annotation on a constructor that shows how the parameters of + * that constructor correspond to the constructed object's getter + * methods. For example: + *

+ *
+ *
+ *         public class MemoryUsage {
+ *             // standard JavaBean conventions with getters
+ *             @ConstructorParameters({"init", "used", "committed", "max"})
+ *             public MemoryUsage(long init, long used,
+ *                                long committed, long max) {...}
+ *             public long getInit() {...}
+ *             public long getUsed() {...}
+ *             public long getCommitted() {...}
+ *             public long getMax() {...}
+ *         }
+ *     
+ *
+ *

+ * The annotation shows that the first parameter of the constructor + * can be retrieved with the {@code getInit()} method, the second one with + * the {@code getUsed()} method, and so on. Since parameter names are not in + * general available at runtime, without the annotation there would be + * no way of knowing which parameter corresponds to which property. + *

+ *

+ * If a constructor is annotated by the both {@code @java.beans.ConstructorProperties} + * and {@code @javax.management.ConstructorParameters} annotations + * the JMX introspection will give an absolute precedence to the latter one. + *

+ * + * @since 1.9 + */ +@Documented @Target(CONSTRUCTOR) @Retention(RUNTIME) +public @interface ConstructorParameters { + /** + *

The getter names.

+ * + * @return the getter names corresponding to the parameters in the + * annotated constructor. + */ + String[] value(); +} diff --git a/jdk/src/java.management/share/classes/javax/management/MXBean.java b/jdk/src/java.management/share/classes/javax/management/MXBean.java index 766e36feda6..8784a5fbaf8 100644 --- a/jdk/src/java.management/share/classes/javax/management/MXBean.java +++ b/jdk/src/java.management/share/classes/javax/management/MXBean.java @@ -153,7 +153,7 @@ public class MemoryUsage implements Serializable {
 public class MemoryUsage {
     // standard JavaBean conventions with getters
-    @ConstructorProperties({"init", "used", "committed", "max"})
+    @ConstructorParameters({"init", "used", "committed", "max"})
     public MemoryUsage(long init, long used,
                        long committed, long max) {...}
     long getInit() {...}
@@ -168,8 +168,8 @@ public class MemoryUsage {
     

The definitions are the same in the two cases, except that with the MXBean, MemoryUsage no longer needs to be marked Serializable (though it can be). On - the other hand, we have added a {@code @ConstructorProperties} annotation - to link the constructor parameters to the corresponding getters. + the other hand, we have added a {@link ConstructorParameters @ConstructorParameters} + annotation to link the constructor parameters to the corresponding getters. We will see more about this below.

MemoryUsage is a model-specific class. @@ -850,18 +850,24 @@ public interface ModuleMXBean { J.

  • Otherwise, if J has at least one public - constructor with a {@link java.beans.ConstructorProperties - ConstructorProperties} annotation, then one - of those constructors (not necessarily always the same one) - will be called to reconstruct an instance of J. + constructor with either {@link javax.management.ConstructorParameters + @javax.management.ConstructorParameters} or + {@code @java.beans.ConstructoProperties} annotation, then one of those + constructors (not necessarily always the same one) will be called to + reconstruct an instance of J. + If a constructor is annotated with both + {@code @javax.management.ConstructorParameters} and + {@code @java.beans.ConstructorProperties}, + {@code @javax.management.ConstructorParameters} will be used and + {@code @java.beans.ConstructorProperties} will be ignored. Every such annotation must list as many strings as the constructor has parameters; each string must name a property corresponding to a getter of J; and the type of this getter must be the same as the corresponding constructor parameter. It is not an error for there to be getters that - are not mentioned in the {@code ConstructorProperties} annotation - (these may correspond to information that is not needed to - reconstruct the object).

    + are not mentioned in the {@code @ConstructorParameters} or + {@code @ConstructorProperties} annotations (these may correspond to + information that is not needed to reconstruct the object).

    An instance of J is reconstructed by calling a constructor with the appropriate reconstructed items from the @@ -871,9 +877,10 @@ public interface ModuleMXBean { CompositeData} might come from an earlier version of J where not all the items were present. A constructor is applicable if all the properties named - in its {@code ConstructorProperties} annotation are present as items - in the {@code CompositeData}. If no constructor is - applicable, then the attempt to reconstruct J fails.

    + in its {@code @ConstructorParameters} or {@code @ConstructorProperties} + annotation are present as items in the {@code CompositeData}. + If no constructor is applicable, then the attempt to reconstruct + J fails.

    For any possible combination of properties, it must be the case that either (a) there are no applicable constructors, or @@ -909,8 +916,9 @@ public interface ModuleMXBean {

  • Otherwise, J is not reconstructible.

  • -

    Rule 2 is not applicable to subset Profiles of Java SE that do not - include the {@code java.beans} package. When targeting a runtime that does +

    When only {@code @java.beans.ConstructorProperties} is present then + rule 2 is not applicable to subset Profiles of Java SE that do not include + the {@code java.beans} package. When targeting a runtime that does not include the {@code java.beans} package, and where there is a mismatch between the compile-time and runtime environment whereby J is compiled with a public constructor and the {@code ConstructorProperties} @@ -957,14 +965,14 @@ public class NamedNumber { -

  • Public constructor with @ConstructorProperties annotation: +
  • Public constructor with @ConstructorParameters annotation:
     public class NamedNumber {
         public int getNumber() {return number;}
         public String getName() {return name;}
    -    @ConstructorProperties({"number", "name"})
    +    @ConstructorParameters({"number", "name"})
         public NamedNumber(int number, String name) {
             this.number = number;
             this.name = name;
    diff --git a/jdk/test/javax/management/Introspector/AnnotationSecurityTest.java b/jdk/test/javax/management/Introspector/AnnotationSecurityTest.java
    index 2d07a0a61bd..0afb509272c 100644
    --- a/jdk/test/javax/management/Introspector/AnnotationSecurityTest.java
    +++ b/jdk/test/javax/management/Introspector/AnnotationSecurityTest.java
    @@ -27,8 +27,7 @@
      * @summary Test that having a security manager doesn't trigger a
      *          NotCompliantMBeanException
      * @author Daniel Fuchs, Yves Joan
    - * @modules java.desktop
    - *          java.management
    + * @modules java.management
      * @run clean AnnotationSecurityTest Described UnDescribed DescribedMBean
      *            UnDescribedMBean SqeDescriptorKey DescribedMX DescribedMXBean
      * @run build AnnotationSecurityTest Described UnDescribed DescribedMBean
    @@ -40,13 +39,8 @@
     import java.io.File;
     import java.io.IOException;
     
    -import java.lang.annotation.Annotation;
     import java.lang.management.ManagementFactory;
    -import java.lang.reflect.AnnotatedElement;
     import java.lang.reflect.Method;
    -import java.lang.reflect.UndeclaredThrowableException;
    -
    -import javax.management.JMException;
     import javax.management.MBeanServer;
     import javax.management.ObjectName;
     /**
    diff --git a/jdk/test/javax/management/Introspector/Described.java b/jdk/test/javax/management/Introspector/Described.java
    index 1ef62efb54c..2b9d0684755 100644
    --- a/jdk/test/javax/management/Introspector/Described.java
    +++ b/jdk/test/javax/management/Introspector/Described.java
    @@ -25,7 +25,7 @@
      *
      * Used by AnnotationSecurityTest.java
      **/
    -import java.beans.ConstructorProperties;
    +import javax.management.ConstructorParameters;
     
     /**
      * An MBean used by AnnotationSecurityTest.java
    @@ -37,7 +37,7 @@ public class Described implements DescribedMBean {
         public Described() {}
     
         @SqeDescriptorKey("ONE PARAMETER CONSTRUCTOR Described")
    -    @ConstructorProperties({"name", "unused"})
    +    @ConstructorParameters({"name", "unused"})
         public Described(@SqeDescriptorKey("CONSTRUCTOR PARAMETER name")String name,
                 @SqeDescriptorKey("CONSTRUCTOR PARAMETER unused")String unused) {
             this.name = name ;
    diff --git a/jdk/test/javax/management/Introspector/DescribedMX.java b/jdk/test/javax/management/Introspector/DescribedMX.java
    index 625cc65f8af..b6e8c2652dc 100644
    --- a/jdk/test/javax/management/Introspector/DescribedMX.java
    +++ b/jdk/test/javax/management/Introspector/DescribedMX.java
    @@ -25,7 +25,7 @@
      *
      * Used by AnnotationSecurityTest.java
      **/
    -import java.beans.ConstructorProperties;
    +import javax.management.ConstructorParameters;
     
     /**
      * An MXBean used by AnnotationSecurityTest.java
    @@ -37,7 +37,7 @@ public class DescribedMX implements DescribedMXBean {
         public DescribedMX() {}
     
         @SqeDescriptorKey("ONE PARAMETER CONSTRUCTOR DescribedMX")
    -    @ConstructorProperties({"name", "unused"})
    +    @ConstructorParameters({"name", "unused"})
         public DescribedMX(@SqeDescriptorKey("CONSTRUCTOR PARAMETER name")String name,
                 @SqeDescriptorKey("CONSTRUCTOR PARAMETER unused")String unused) {
             this.name = name ;
    diff --git a/jdk/test/javax/management/Introspector/LegacyConstructorPropertiesTest.java b/jdk/test/javax/management/Introspector/LegacyConstructorPropertiesTest.java
    new file mode 100644
    index 00000000000..4848aad5473
    --- /dev/null
    +++ b/jdk/test/javax/management/Introspector/LegacyConstructorPropertiesTest.java
    @@ -0,0 +1,106 @@
    +
    +/*
    + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
    + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    + *
    + * This code is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU General Public License version 2 only, as
    + * published by the Free Software Foundation.
    + *
    + * This code is distributed in the hope that it will be useful, but WITHOUT
    + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    + * version 2 for more details (a copy is included in the LICENSE file that
    + * accompanied this code).
    + *
    + * You should have received a copy of the GNU General Public License version
    + * 2 along with this work; if not, write to the Free Software Foundation,
    + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    + *
    + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    + * or visit www.oracle.com if you need additional information or have any
    + * questions.
    + */
    +
    +import java.beans.ConstructorProperties;
    +import javax.management.ConstructorParameters;
    +import javax.management.MBeanServer;
    +import javax.management.MBeanServerFactory;
    +import javax.management.ObjectName;
    +
    +/*
    + * @test
    + * @bug 7199353
    + * @summary Asserts that 'java.beans.ConstructorProperties' annotation is still
    + *          recognized and properly handled for custom types mapped to open types.
    + *          Also, makes sure that if the same constructor is annotated by both
    + *          j.b.ConstructorProperties and j.m.ConstructorProperties annotations
    + *          only j.m.ConstructorProperties annotation is considered.
    + * @author Jaroslav Bachorik
    + * @modules java.management
    + *          java.desktop
    + * @run main LegacyConstructorPropertiesTest
    + */
    +
    +public class LegacyConstructorPropertiesTest {
    +    public static class CustomType {
    +        private String name;
    +        private int value;
    +        @ConstructorProperties({"name", "value"})
    +        public CustomType(String name, int value) {
    +            this.name = name;
    +            this.value = value;
    +        }
    +
    +        // if @java.beans.ConstructorProperties would be used
    +        // the introspector would choke on this
    +        @ConstructorProperties("noname")
    +        @ConstructorParameters("name")
    +        public CustomType(String name) {
    +            this.name = name;
    +            this.value = -1;
    +        }
    +
    +        public String getName() {
    +            return name;
    +        }
    +
    +        public void setName(String name) {
    +            this.name = name;
    +        }
    +
    +        public int getValue() {
    +            return value;
    +        }
    +
    +        public void setValue(int value) {
    +            this.value = value;
    +        }
    +    }
    +
    +    public static interface CustomMXBean {
    +        public CustomType getProp();
    +        public void setProp(CustomType prop);
    +    }
    +
    +    public static final class Custom implements CustomMXBean {
    +        private CustomType prop;
    +
    +        @Override
    +        public CustomType getProp() {
    +            return prop;
    +        }
    +
    +        @Override
    +        public void setProp(CustomType prop) {
    +            this.prop = prop;
    +        }
    +    }
    +
    +    public static void main(String[] args) throws Exception {
    +        MBeanServer mbs = MBeanServerFactory.createMBeanServer();
    +        CustomMXBean mbean = new Custom();
    +
    +        mbs.registerMBean(mbean, ObjectName.getInstance("test:type=Custom"));
    +    }
    +}
    diff --git a/jdk/test/javax/management/mxbean/AmbiguousConstructorTest.java b/jdk/test/javax/management/mxbean/AmbiguousConstructorTest.java
    index 2b251f66d26..0766d1a8050 100644
    --- a/jdk/test/javax/management/mxbean/AmbiguousConstructorTest.java
    +++ b/jdk/test/javax/management/mxbean/AmbiguousConstructorTest.java
    @@ -26,15 +26,13 @@
      * @bug 6175517 6278707
      * @summary Test that ambiguous ConstructorProperties annotations are detected.
      * @author Eamonn McManus
    - * @modules java.desktop
    - *          java.management
    + * @modules java.management
      * @run clean AmbiguousConstructorTest
      * @run build AmbiguousConstructorTest
      * @run main AmbiguousConstructorTest
      */
     
    -import java.beans.ConstructorProperties;
    -import java.io.InvalidObjectException;
    +import javax.management.ConstructorParameters;
     import javax.management.*;
     
     public class AmbiguousConstructorTest {
    @@ -76,13 +74,13 @@ public class AmbiguousConstructorTest {
             public int getC() {return 0;}
             public long getD() {return 0;}
     
    -        @ConstructorProperties({"a", "b"})
    +        @ConstructorParameters({"a", "b"})
             public Unambiguous(byte a, short b) {}
     
    -        @ConstructorProperties({"b", "c"})
    +        @ConstructorParameters({"b", "c"})
             public Unambiguous(short b, int c) {}
     
    -        @ConstructorProperties({"a", "b", "c"})
    +        @ConstructorParameters({"a", "b", "c"})
             public Unambiguous(byte a, short b, int c) {}
         }
     
    @@ -92,13 +90,13 @@ public class AmbiguousConstructorTest {
             public int getC() {return 0;}
             public long getD() {return 0;}
     
    -        @ConstructorProperties({"a", "b"})
    +        @ConstructorParameters({"a", "b"})
             public Ambiguous(byte a, short b) {}
     
    -        @ConstructorProperties({"b", "c"})
    +        @ConstructorParameters({"b", "c"})
             public Ambiguous(short b, int c) {}
     
    -        @ConstructorProperties({"a", "b", "c", "d"})
    +        @ConstructorParameters({"a", "b", "c", "d"})
             public Ambiguous(byte a, short b, int c, long d) {}
         }
     
    diff --git a/jdk/test/javax/management/mxbean/ExceptionDiagnosisTest.java b/jdk/test/javax/management/mxbean/ExceptionDiagnosisTest.java
    index 89ca763cfea..16ece4db261 100644
    --- a/jdk/test/javax/management/mxbean/ExceptionDiagnosisTest.java
    +++ b/jdk/test/javax/management/mxbean/ExceptionDiagnosisTest.java
    @@ -26,11 +26,10 @@
      * @bug 6713777
      * @summary Test that exception messages include all relevant information
      * @author Eamonn McManus
    - * @modules java.desktop
    - *          java.management
    + * @modules java.management
      */
     
    -import java.beans.ConstructorProperties;
    +import javax.management.ConstructorParameters;
     import java.io.File;
     import java.lang.reflect.InvocationTargetException;
     import java.lang.reflect.Method;
    @@ -131,7 +130,7 @@ public class ExceptionDiagnosisTest {
         }
     
         public static class CaseProb {
    -        @ConstructorProperties({"urlPath"})
    +        @ConstructorParameters({"urlPath"})
             public CaseProb(String urlPath) {}
     
             public String getURLPath() {return null;}
    diff --git a/jdk/test/javax/management/mxbean/LeakTest.java b/jdk/test/javax/management/mxbean/LeakTest.java
    index 982ec225d4b..43ac996ab5e 100644
    --- a/jdk/test/javax/management/mxbean/LeakTest.java
    +++ b/jdk/test/javax/management/mxbean/LeakTest.java
    @@ -25,8 +25,7 @@
      * @bug 6482247
      * @summary Test that creating MXBeans does not introduce memory leaks.
      * @author Eamonn McManus
    - * @modules java.desktop
    - *          java.management
    + * @modules java.management
      * @run build LeakTest RandomMXBeanTest MerlinMXBean TigerMXBean
      * @run main LeakTest
      */
    diff --git a/jdk/test/javax/management/mxbean/MXBeanTest.java b/jdk/test/javax/management/mxbean/MXBeanTest.java
    index 9017d497a0d..6123be2365e 100644
    --- a/jdk/test/javax/management/mxbean/MXBeanTest.java
    +++ b/jdk/test/javax/management/mxbean/MXBeanTest.java
    @@ -27,8 +27,7 @@
      * @summary General MXBean test.
      * @author Eamonn McManus
      * @author Jaroslav Bachorik
    - * @modules java.desktop
    - *          java.management
    + * @modules java.management
      * @run clean MXBeanTest MerlinMXBean TigerMXBean
      * @run build MXBeanTest MerlinMXBean TigerMXBean
      * @run main MXBeanTest
    diff --git a/jdk/test/javax/management/mxbean/PropertyNamesTest.java b/jdk/test/javax/management/mxbean/PropertyNamesTest.java
    index d8f6845ffd2..534f76c11d9 100644
    --- a/jdk/test/javax/management/mxbean/PropertyNamesTest.java
    +++ b/jdk/test/javax/management/mxbean/PropertyNamesTest.java
    @@ -26,14 +26,13 @@
      * @bug 6175517
      * @summary Test the PropertyNames annotation with MXBeans
      * @author Eamonn McManus
    - * @modules java.desktop
    - *          java.management
    + * @modules java.management
      * @run clean PropertyNamesTest
      * @run build PropertyNamesTest
      * @run main PropertyNamesTest
      */
     
    -import java.beans.ConstructorProperties;
    +import javax.management.ConstructorParameters;
     import java.util.Collections;
     import java.util.List;
     import javax.management.JMX;
    @@ -95,7 +94,7 @@ public class PropertyNamesTest {
         }
     
         public static class Point {
    -        @ConstructorProperties({"x", "y"})
    +        @ConstructorParameters({"x", "y"})
             public Point(int x, int y) {
                 this.x = x;
                 this.y = y;
    @@ -123,17 +122,17 @@ public class PropertyNamesTest {
         }
     
         public static class Evolve {
    -        @ConstructorProperties({"oldInt"})
    +        @ConstructorParameters({"oldInt"})
             public Evolve(int oldInt) {
                 this(oldInt, "defaultString");
             }
     
    -        @ConstructorProperties({"oldInt", "newString"})
    +        @ConstructorParameters({"oldInt", "newString"})
             public Evolve(int oldInt, String newString) {
                 this(oldInt, newString, Collections.emptyList());
             }
     
    -        @ConstructorProperties({"oldInt", "newString", "newerList"})
    +        @ConstructorParameters({"oldInt", "newString", "newerList"})
             public Evolve(int oldInt, String newString, List newerList) {
                 this.oldInt = oldInt;
                 this.newString = newString;
    diff --git a/jdk/test/javax/management/mxbean/TigerMXBean.java b/jdk/test/javax/management/mxbean/TigerMXBean.java
    index cfc47a90b2c..e4129b77806 100644
    --- a/jdk/test/javax/management/mxbean/TigerMXBean.java
    +++ b/jdk/test/javax/management/mxbean/TigerMXBean.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -21,7 +21,7 @@
      * questions.
      */
     
    -import java.beans.ConstructorProperties;
    +import javax.management.ConstructorParameters;
     import java.util.Arrays;
     import java.util.Collections;
     import java.util.HashSet;
    @@ -42,7 +42,7 @@ import javax.management.openmbean.TabularType;
     public interface TigerMXBean {
     
         class Point {
    -        @ConstructorProperties({"x", "y"})
    +        @ConstructorParameters({"x", "y"})
             public Point(double x, double y) {
                 this.x = x;
                 this.y = y;
    
    From 206483e8b3a6992650461fe6e118131825ea8f2e Mon Sep 17 00:00:00 2001
    From: Sergey Bylokhov 
    Date: Sun, 18 Oct 2015 13:33:20 +0300
    Subject: [PATCH 06/31] 6815345: java.awt.Component.createImage(int width,int
     height) should remove behavioral optionality
    
    Reviewed-by: prr, ssadetsky
    ---
     .../share/classes/java/awt/Component.java     |  67 ++++++-----
     .../Component/CreateImage/CreateImage.java    | 111 ++++++++++++++++++
     2 files changed, 146 insertions(+), 32 deletions(-)
     create mode 100644 jdk/test/java/awt/Component/CreateImage/CreateImage.java
    
    diff --git a/jdk/src/java.desktop/share/classes/java/awt/Component.java b/jdk/src/java.desktop/share/classes/java/awt/Component.java
    index 3c50dceecce..72c459943b3 100644
    --- a/jdk/src/java.desktop/share/classes/java/awt/Component.java
    +++ b/jdk/src/java.desktop/share/classes/java/awt/Component.java
    @@ -3622,18 +3622,17 @@ public abstract class Component implements ImageObserver, MenuContainer,
         }
     
         /**
    -     * Creates an off-screen drawable image
    -     *     to be used for double buffering.
    -     * @param     width the specified width
    -     * @param     height the specified height
    -     * @return    an off-screen drawable image, which can be used for double
    -     *    buffering.  The return value may be null if the
    -     *    component is not displayable.  This will always happen if
    -     *    GraphicsEnvironment.isHeadless() returns
    -     *    true.
    +     * Creates an off-screen drawable image to be used for double buffering.
    +     *
    +     * @param  width the specified width
    +     * @param  height the specified height
    +     * @return an off-screen drawable image, which can be used for double
    +     *         buffering. The {@code null} value if the component is not
    +     *         displayable or {@code GraphicsEnvironment.isHeadless()} returns
    +     *         {@code true}.
          * @see #isDisplayable
          * @see GraphicsEnvironment#isHeadless
    -     * @since     1.0
    +     * @since 1.0
          */
         public Image createImage(int width, int height) {
             ComponentPeer peer = this.peer;
    @@ -3646,19 +3645,19 @@ public abstract class Component implements ImageObserver, MenuContainer,
         }
     
         /**
    -     * Creates a volatile off-screen drawable image
    -     *     to be used for double buffering.
    -     * @param     width the specified width.
    -     * @param     height the specified height.
    -     * @return    an off-screen drawable image, which can be used for double
    -     *    buffering.  The return value may be null if the
    -     *    component is not displayable.  This will always happen if
    -     *    GraphicsEnvironment.isHeadless() returns
    -     *    true.
    +     * Creates a volatile off-screen drawable image to be used for double
    +     * buffering.
    +     *
    +     * @param  width the specified width
    +     * @param  height the specified height
    +     * @return an off-screen drawable image, which can be used for double
    +     *         buffering. The {@code null} value if the component is not
    +     *         displayable or {@code GraphicsEnvironment.isHeadless()} returns
    +     *         {@code true}.
          * @see java.awt.image.VolatileImage
          * @see #isDisplayable
          * @see GraphicsEnvironment#isHeadless
    -     * @since     1.4
    +     * @since 1.4
          */
         public VolatileImage createVolatileImage(int width, int height) {
             ComponentPeer peer = this.peer;
    @@ -3674,22 +3673,26 @@ public abstract class Component implements ImageObserver, MenuContainer,
         }
     
         /**
    -     * Creates a volatile off-screen drawable image, with the given capabilities.
    -     * The contents of this image may be lost at any time due
    -     * to operating system issues, so the image must be managed
    -     * via the VolatileImage interface.
    -     * @param width the specified width.
    -     * @param height the specified height.
    -     * @param caps the image capabilities
    -     * @exception AWTException if an image with the specified capabilities cannot
    -     * be created
    -     * @return a VolatileImage object, which can be used
    -     * to manage surface contents loss and capabilities.
    +     * Creates a volatile off-screen drawable image, with the given
    +     * capabilities. The contents of this image may be lost at any time due to
    +     * operating system issues, so the image must be managed via the
    +     * {@code VolatileImage} interface.
    +     *
    +     * @param  width the specified width
    +     * @param  height the specified height
    +     * @param  caps the image capabilities
    +     * @return a VolatileImage object, which can be used to manage surface
    +     *         contents loss and capabilities. The {@code null} value if the
    +     *         component is not displayable or
    +     *         {@code GraphicsEnvironment.isHeadless()} returns {@code true}.
    +     * @throws AWTException if an image with the specified capabilities cannot
    +     *         be created
          * @see java.awt.image.VolatileImage
          * @since 1.4
          */
         public VolatileImage createVolatileImage(int width, int height,
    -                                             ImageCapabilities caps) throws AWTException {
    +                                             ImageCapabilities caps)
    +            throws AWTException {
             // REMIND : check caps
             return createVolatileImage(width, height);
         }
    diff --git a/jdk/test/java/awt/Component/CreateImage/CreateImage.java b/jdk/test/java/awt/Component/CreateImage/CreateImage.java
    new file mode 100644
    index 00000000000..aa977ce0ac5
    --- /dev/null
    +++ b/jdk/test/java/awt/Component/CreateImage/CreateImage.java
    @@ -0,0 +1,111 @@
    +/*
    + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
    + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    + *
    + * This code is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU General Public License version 2 only, as
    + * published by the Free Software Foundation.
    + *
    + * This code is distributed in the hope that it will be useful, but WITHOUT
    + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    + * version 2 for more details (a copy is included in the LICENSE file that
    + * accompanied this code).
    + *
    + * You should have received a copy of the GNU General Public License version
    + * 2 along with this work; if not, write to the Free Software Foundation,
    + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    + *
    + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    + * or visit www.oracle.com if you need additional information or have any
    + * questions.
    + */
    +
    +import java.awt.AWTException;
    +import java.awt.Button;
    +import java.awt.Component;
    +import java.awt.EventQueue;
    +import java.awt.Frame;
    +import java.awt.GraphicsEnvironment;
    +
    +import javax.swing.JButton;
    +
    +/**
    + * @test
    + * @bug 6815345
    + * @run main CreateImage
    + * @run main/othervm -Djava.awt.headless=true CreateImage
    + */
    +public final class CreateImage {
    +
    +    public static void main(final String[] args) throws Exception {
    +        EventQueue.invokeAndWait(CreateImage::test);
    +    }
    +
    +    private static void test() {
    +        final JButton jbutton1 = new JButton();
    +        final JButton jbutton2 = new JButton();
    +
    +        if (GraphicsEnvironment.isHeadless()) {
    +            checkCreateImage(jbutton1, true);
    +            checkCreateImage(jbutton2, true);
    +            return;
    +        }
    +
    +        final Frame frame = new Frame();
    +        final Button button1 = new Button();
    +        final Button button2 = new Button();
    +        try {
    +            // all components are not displayable
    +            checkCreateImage(frame, true);
    +            checkCreateImage(button1, true);
    +            checkCreateImage(button2, true);
    +            checkCreateImage(jbutton1, true);
    +            checkCreateImage(jbutton2, true);
    +
    +            // some components added to the non-displayable frame
    +            frame.add(button1);
    +            frame.add(jbutton1);
    +            checkCreateImage(button1, true);
    +            checkCreateImage(jbutton1, true);
    +            frame.pack();
    +
    +            // tests previously added components when the frame is displayable
    +            checkCreateImage(frame, false);
    +            checkCreateImage(button1, false);
    +            checkCreateImage(jbutton1, false);
    +
    +            // some components added to the displayable frame
    +            frame.add(button2);
    +            frame.add(jbutton2);
    +            checkCreateImage(button2, false);
    +            checkCreateImage(jbutton2, false);
    +
    +        } finally {
    +            frame.dispose();
    +        }
    +        // tests all components after the frame became non-displayable again
    +        checkCreateImage(frame, true);
    +        checkCreateImage(button1, true);
    +        checkCreateImage(button2, true);
    +        checkCreateImage(jbutton1, true);
    +        checkCreateImage(jbutton2, true);
    +    }
    +
    +    private static void checkCreateImage(final Component comp,
    +                                         final boolean isNull) {
    +        if ((comp.createImage(10, 10) != null) == isNull) {
    +            throw new RuntimeException("Image is wrong");
    +        }
    +        if ((comp.createVolatileImage(10, 10) != null) == isNull) {
    +            throw new RuntimeException("Image is wrong");
    +        }
    +        try {
    +            if ((comp.createVolatileImage(10, 10, null) != null) == isNull) {
    +                throw new RuntimeException("Image is wrong");
    +            }
    +        } catch (final AWTException ignored) {
    +            // this check is not applicable
    +        }
    +    }
    +}
    
    From 1127171d12fbf88449682447644348f5f32b0b0e Mon Sep 17 00:00:00 2001
    From: Renjith Alexander 
    Date: Tue, 20 Oct 2015 12:42:21 +0300
    Subject: [PATCH 07/31] 8136592: [TEST_BUG] Fix 2 platform-specific closed
     regtests for jigsaw
    
    Reviewed-by: serb, yan
    ---
     .../GraphicsConfigTest.java                   | 159 ++++++++++++++++++
     .../FocusEmptyListTest.html                   |  47 ++++++
     .../FocusEmptyListTest.java                   |  96 +++++++++++
     3 files changed, 302 insertions(+)
     create mode 100644 jdk/test/java/awt/EmbeddedFrame/GraphicsConfigTest/GraphicsConfigTest.java
     create mode 100644 jdk/test/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.html
     create mode 100644 jdk/test/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.java
    
    diff --git a/jdk/test/java/awt/EmbeddedFrame/GraphicsConfigTest/GraphicsConfigTest.java b/jdk/test/java/awt/EmbeddedFrame/GraphicsConfigTest/GraphicsConfigTest.java
    new file mode 100644
    index 00000000000..f2d56675c91
    --- /dev/null
    +++ b/jdk/test/java/awt/EmbeddedFrame/GraphicsConfigTest/GraphicsConfigTest.java
    @@ -0,0 +1,159 @@
    +/*
    + * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
    + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    + *
    + * This code is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU General Public License version 2 only, as
    + * published by the Free Software Foundation.
    + *
    + * This code is distributed in the hope that it will be useful, but WITHOUT
    + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    + * version 2 for more details (a copy is included in the LICENSE file that
    + * accompanied this code).
    + *
    + * You should have received a copy of the GNU General Public License version
    + * 2 along with this work; if not, write to the Free Software Foundation,
    + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    + *
    + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    + * or visit www.oracle.com if you need additional information or have any
    + * questions.
    + */
    +
    +/*
    + * @test
    + * @bug 6356322
    + * @summary Tests that embedded frame's graphics configuration is updated
    + *          correctly when it is moved to another screen in multiscreen system,
    + *          XToolkit
    + * @author artem.ananiev@sun.com: area=awt.multiscreen
    + * @requires (os.family == "linux") | (os.family == "solaris")
    + * @modules java.desktop/sun.awt
    + *          java.desktop/sun.awt.X11
    + *          java.desktop/java.awt.peer
    + * @run main GraphicsConfigTest
    + */
    +
    +import java.awt.*;
    +import java.awt.peer.*;
    +import java.lang.reflect.*;
    +import java.util.*;
    +import sun.awt.*;
    +
    +public class GraphicsConfigTest {
    +
    +    private static void init()
    +        throws InterruptedException, AWTException {
    +        if (!isXToolkit()) {
    +            System.err.println("The test should be run only on XToolkit");
    +            return;
    +        }
    +
    +        GraphicsEnvironment ge =
    +                GraphicsEnvironment.getLocalGraphicsEnvironment();
    +        GraphicsDevice[] gds = ge.getScreenDevices();
    +        if (gds.length < 2) {
    +            System.err.println("The test should be run only in"
    +                + " multiscreen configuration");
    +            return;
    +        }
    +
    +        boolean xinerama = Arrays.stream(gds)
    +            .map((gd) -> gd.getDefaultConfiguration().getBounds())
    +            .filter((r) -> r.x != 0 || r.y != 0).findFirst().isPresent();
    +
    +        if (!xinerama) {
    +            System.err.println("The test should be run only with Xinerama ON");
    +            return;
    +        }
    +
    +        Rectangle r0 = gds[0].getDefaultConfiguration().getBounds();
    +        Rectangle r1 = gds[1].getDefaultConfiguration().getBounds();
    +
    +        System.setProperty("sun.awt.xembedserver", "true");
    +        Frame f = new Frame("F");
    +        try {
    +            final Robot robot = new Robot();
    +
    +            f.setBounds(r0.x + 100, r0.y + 100, 200, 200);
    +            f.setVisible(true);
    +            robot.waitForIdle();
    +            Thread.sleep(1000);
    +
    +            Canvas c = new Canvas();
    +            f.add(c);
    +            AWTAccessor.ComponentAccessor acc =
    +                        AWTAccessor.getComponentAccessor();
    +            WindowIDProvider wip = acc.getPeer(c);
    +            long h = wip.getWindow();
    +
    +            EmbeddedFrame e = createEmbeddedFrame(h);
    +            acc.getPeer(e).setBoundsPrivate(0, 0, 100,
    +                100); // triggers XConfigureEvent
    +            e.registerListeners();
    +            e.setVisible(true);
    +            robot.waitForIdle();
    +            Thread.sleep(1000);
    +
    +            if (!checkGC(f, e)) {
    +                throw new RuntimeException("Failed at checkpoint 1");
    +            }
    +
    +            f.setLocation(r1.x + 100, r1.y + 100);
    +            Thread.sleep(100);
    +            acc.getPeer(e).setBoundsPrivate(0, 0, 101,
    +                101); // triggers XConfigureEvent
    +            robot.waitForIdle();
    +            Thread.sleep(1000);
    +
    +            if (!checkGC(f, e)) {
    +                throw new RuntimeException("Failed at checkpoint 2");
    +            }
    +
    +            f.setLocation(r0.x + 100, r0.y + 100);
    +            Thread.sleep(100);
    +            acc.getPeer(e).setBoundsPrivate(0, 0, 102,
    +                102); // triggers XConfigureEvent
    +            robot.waitForIdle();
    +            Thread.sleep(1000);
    +
    +            if (!checkGC(f, e)) {
    +                throw new RuntimeException("Failed at checkpoint 3");
    +            }
    +
    +        } finally {
    +            f.dispose();
    +        }
    +    }
    +
    +    private static boolean isXToolkit() {
    +        return Toolkit.getDefaultToolkit().getClass()
    +                        .getName().equals("sun.awt.X11.XToolkit");
    +    }
    +
    +    private static EmbeddedFrame createEmbeddedFrame(long window) {
    +        try {
    +            Class cl = Class.forName("sun.awt.X11.XEmbeddedFrame");
    +            Constructor cons = cl.getConstructor(
    +                new Class[]{Long.TYPE, Boolean.TYPE});
    +            return (EmbeddedFrame) cons.newInstance(new Object[]{window, true});
    +        } catch (Exception e) {
    +            e.printStackTrace();
    +            throw new RuntimeException("Can't create embedded frame");
    +        }
    +    }
    +
    +    private static boolean checkGC(Component c, Component d) {
    +        GraphicsConfiguration g1 = c.getGraphicsConfiguration();
    +        System.err.println(g1);
    +        GraphicsConfiguration g2 = d.getGraphicsConfiguration();
    +        System.err.println(g2);
    +
    +        return g1.equals(g2);
    +    }
    +
    +    public static void main(String args[]) throws InterruptedException, AWTException {
    +        init();
    +    }
    +}
    diff --git a/jdk/test/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.html b/jdk/test/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.html
    new file mode 100644
    index 00000000000..5bbd8f7f197
    --- /dev/null
    +++ b/jdk/test/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.html
    @@ -0,0 +1,47 @@
    +
    +
    +
    +
    + FocusEmptyListTest 
    +
    +
    +
    +

    FocusEmptyListTest
    Bug ID: 6387275

    + +

    This is an AUTOMATIC test, simply wait for completion

    + + + + + diff --git a/jdk/test/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.java b/jdk/test/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.java new file mode 100644 index 00000000000..59d8c61269c --- /dev/null +++ b/jdk/test/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + test + @bug 6387275 + @summary List: the focus is at the top of the first item, XAWT + @author Dmitry.Cherepanov@SUN.COM area=awt.list + @run applet FocusEmptyListTest.html +*/ + +import java.applet.Applet; +import java.awt.*; +import java.lang.reflect.*; +import java.awt.peer.ListPeer; + +import sun.awt.AWTAccessor; + +public class FocusEmptyListTest extends Applet { + + public void init() { + setLayout(new BorderLayout()); + }//End init() + + public void start() { + boolean isXToolkit = Toolkit.getDefaultToolkit() + .getClass().getName().equals("sun.awt.X11.XToolkit"); + if (!isXToolkit) { + System.out.println("The test is XAWT-only."); + return; + } + + List list = new List(); + Object isIndexDisplayed = null; + setLayout(new FlowLayout()); + + getToolkit().addAWTEventListener(System.out::println, + AWTEvent.FOCUS_EVENT_MASK | AWTEvent.WINDOW_FOCUS_EVENT_MASK); + + add(list); + list.add("item1"); + + setSize(200, 200); + setVisible(true); + validate(); + + list.removeAll(); + + try { + + // peer = List.getPeer() + ListPeer peer = AWTAccessor.getComponentAccessor().getPeer(list); + System.out.println("peer = " + peer); + Class peerClass = peer.getClass(); + System.out.println("peer's class = " + peerClass); + + // isIndexDisplayed = peer.isIndexDisplayed(-1) + Method isIndexDisplayedM + = peerClass.getDeclaredMethod("isIndexDisplayed", Integer.TYPE); + System.out.println("method = " + isIndexDisplayedM); + isIndexDisplayedM.setAccessible(true); + isIndexDisplayed = isIndexDisplayedM.invoke(peer, -1); + System.out.println("isIndexDisplayed=" + isIndexDisplayed); + + } catch (Throwable thr) { + throw new RuntimeException("TEST FAILED: " + thr); + } + + if ((Boolean) isIndexDisplayed) { + throw new RuntimeException("TEST FAILED: -1 should be" + + " invisible index"); + } + + }// start() + +}// class AutomaticAppletTest From d1544f66ebadfafcfb9c9d79442c19aa99145c6b Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Tue, 20 Oct 2015 15:42:59 +0300 Subject: [PATCH 08/31] 8011616: JWindow.getLocation and JWindow.getLocationOnScreen return different values on Unity Reviewed-by: alexsch, serb --- .../unix/classes/sun/awt/X11/XWindow.java | 3 + .../ScreenLocation/ScreenLocationTest.java | 92 +++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 jdk/test/java/awt/Window/ScreenLocation/ScreenLocationTest.java diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java index 597020da9e3..a90a938086d 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java @@ -992,10 +992,13 @@ class XWindow extends XBaseWindow implements X11ComponentPeer { // if ( Check if it's a resize, a move, or a stacking order change ) // { Rectangle bounds = getBounds(); + final ComponentAccessor acc = AWTAccessor.getComponentAccessor(); if (!bounds.getSize().equals(oldBounds.getSize())) { + acc.setSize(target, bounds.width, bounds.height); postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_RESIZED)); } if (!bounds.getLocation().equals(oldBounds.getLocation())) { + acc.setLocation(target, bounds.x, bounds.y); postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_MOVED)); } // } diff --git a/jdk/test/java/awt/Window/ScreenLocation/ScreenLocationTest.java b/jdk/test/java/awt/Window/ScreenLocation/ScreenLocationTest.java new file mode 100644 index 00000000000..ef89ef0c0cb --- /dev/null +++ b/jdk/test/java/awt/Window/ScreenLocation/ScreenLocationTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 8011616 + @summary JWindow.getLocation and JWindow.getLocationOnScreen return different + values on Unity + @author Semyon Sadetsky + */ + +import java.awt.*; + +public class ScreenLocationTest { + + + public static void main(String[] args) throws Exception { + testLocation(); + testSize(); + System.out.println("ok"); + } + + public static void testLocation() throws Exception { + Window window = new Window((Frame) null); + window.setSize(100, 100); + window.setLocation(0, 0); + window.setVisible(true); + + Robot robot = new Robot(); + robot.delay(200); + robot.waitForIdle(); + + Point location1 = window.getLocation(); + Point location2 = window.getLocationOnScreen(); + window.setLocation(10000, 10000); + + if (!location1.equals(location2)) { + window.dispose(); + throw new RuntimeException("getLocation is different"); + } + + robot.delay(200); + robot.waitForIdle(); + location1 = window.getLocation(); + location2 = window.getLocationOnScreen(); + + if (!location1.equals(location2)) { + window.dispose(); + throw new RuntimeException("getLocation is different"); + } + + window.dispose(); + } + + public static void testSize() throws Exception { + Window window = new Window((Frame) null); + window.setSize(Integer.MAX_VALUE, Integer.MAX_VALUE); + window.setVisible(true); + + Robot robot = new Robot(); + robot.delay(200); + robot.waitForIdle(); + + Dimension size = window.getSize(); + if (size.width == Integer.MAX_VALUE || + size.height == Integer.MAX_VALUE) { + window.dispose(); + throw new RuntimeException("size is wrong"); + } + + window.dispose(); + } +} From d910e3843fb093117b7118371afc1e4efc71afac Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Tue, 20 Oct 2015 15:59:51 +0300 Subject: [PATCH 09/31] 8022334: After calling frame.toBack() dialog goes to the back on Ubuntu 12.04 Reviewed-by: alexsch, serb --- .../unix/classes/sun/awt/X11/XWindow.java | 3 +- .../MultiWindowApp/MultiWindowAppTest.java | 81 +++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 jdk/test/java/awt/Window/MultiWindowApp/MultiWindowAppTest.java diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java index a90a938086d..42a03359f1f 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java @@ -272,7 +272,8 @@ class XWindow extends XBaseWindow implements X11ComponentPeer { } protected String[] getWMClass() { - return new String[] {XToolkit.getCorrectXIDString(getClass().getName()), XToolkit.getAWTAppClassName()}; + return new String[] {XToolkit.getAWTAppClassName(), + XToolkit.getAWTAppClassName()}; } void setReparented(boolean newValue) { diff --git a/jdk/test/java/awt/Window/MultiWindowApp/MultiWindowAppTest.java b/jdk/test/java/awt/Window/MultiWindowApp/MultiWindowAppTest.java new file mode 100644 index 00000000000..41b4b7fbe5d --- /dev/null +++ b/jdk/test/java/awt/Window/MultiWindowApp/MultiWindowAppTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test @summary After calling frame.toBack() dialog goes to the back on Ubuntu 12.04 + * @bug 8022334 + * @author Semyon Sadetsky + * @run main MultiWindowAppTest + */ + +import java.awt.*; + +public class MultiWindowAppTest { + + public static void main(String[] args) throws Exception { + Window win1 = new Frame(); + Window win2 = new Dialog((Frame) null); + + win1.setBounds(100, 100, 200, 200); + win1.setBackground(Color.RED); + win1.setVisible(true); + + Robot robot = new Robot(); + robot.delay(200); + robot.waitForIdle(); + + win2.setBounds(win1.getBounds()); + win2.setVisible(true); + + robot.delay(200); + robot.waitForIdle(); + + win1.toFront(); + robot.delay(200); + robot.waitForIdle(); + + Point point = win1.getLocationOnScreen(); + Color color = robot.getPixelColor(point.x + 100, point.y + 100); + + if(!color.equals(Color.RED)) { + win1.dispose(); + win2.dispose(); + throw new RuntimeException("Window was not sent to front."); + } + + win1.toBack(); + robot.delay(200); + robot.waitForIdle(); + + color = robot.getPixelColor(point.x + 100, point.y + 100); + + win1.dispose(); + win2.dispose(); + + if(color.equals(Color.RED)) { + throw new RuntimeException("Window was not sent to back."); + } + + System.out.println("ok"); + } +} From 69da2a817d28868dae9fdb6f099e337a4da0f74f Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Tue, 20 Oct 2015 16:55:08 +0300 Subject: [PATCH 10/31] 8130136: Swing window sometimes fails to repaint partially when it becomes exposed Reviewed-by: alexp, serb --- .../libawt/java2d/windows/GDIWindowSurfaceData.cpp | 8 +++++--- .../libawt/java2d/windows/GDIWindowSurfaceData.h | 3 ++- .../native/libawt/windows/awt_Component.cpp | 14 +++++++------- .../windows/native/libawt/windows/awt_Component.h | 6 +++--- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/jdk/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.cpp b/jdk/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.cpp index b52dce038a0..95e737340fb 100644 --- a/jdk/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,8 +114,9 @@ void SetupThreadGraphicsInfo(JNIEnv *env, GDIWinSDOps *wsdo) { // which may've been disposed by this time, and we have // no means of checking against it. if (oldhDC != NULL) { - MoveDCToPassiveList(oldhDC); + MoveDCToPassiveList(oldhDC, info->hWnd); info->hDC = NULL; + info->hWnd = NULL; } if (wsdo->window != NULL){ @@ -150,6 +151,7 @@ void SetupThreadGraphicsInfo(JNIEnv *env, GDIWinSDOps *wsdo) { // Finally, set these new values in the info for this thread info->hDC = hDC; + info->hWnd = wsdo->window; } // cached brush and pen are not associated with any DC, and can be @@ -187,7 +189,7 @@ void DisposeThreadGraphicsInfo(JNIEnv *env, jlong tgi) { if (info->hDC != NULL) { // move the DC from the active dcs list to // the passive dc list to be released later - MoveDCToPassiveList(info->hDC); + MoveDCToPassiveList(info->hDC, info->hWnd); } if (info->clip != NULL) { diff --git a/jdk/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.h b/jdk/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.h index 3dfaa161c02..a954874e9c8 100644 --- a/jdk/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.h +++ b/jdk/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -196,6 +196,7 @@ extern "C" { */ typedef struct { HDC hDC; + HWND hWnd; GDIWinSDOps *wsdo; LONG wsdoTimeStamp; // wsdo creation time stamp. // Other threads may deallocate wsdo diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp index 6b1c1255319..b234ec0221b 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp @@ -1382,7 +1382,7 @@ LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) case WM_AWT_RELEASEDC: { HDC hDC = (HDC)wParam; - MoveDCToPassiveList(hDC); + MoveDCToPassiveList(hDC, GetHWnd()); ReleaseDCList(GetHWnd(), passiveDCList); mr = mrConsume; break; @@ -7165,8 +7165,8 @@ void DCList::AddDCItem(DCItem *newItem) } /** - * Given a DC, remove it from the DC list and return - * TRUE if it exists on the current list. Otherwise + * Given a DC and window handle, remove the DC from the DC list + * and return TRUE if it exists on the current list. Otherwise * return FALSE. * A DC may not exist on the list because it has already * been released elsewhere (for example, the window @@ -7174,14 +7174,14 @@ void DCList::AddDCItem(DCItem *newItem) * thread may also want to release a DC when it notices that * its DC is obsolete for the current window). */ -DCItem *DCList::RemoveDC(HDC hDC) +DCItem *DCList::RemoveDC(HDC hDC, HWND hWnd) { listLock.Enter(); DCItem **prevPtrPtr = &head; DCItem *listPtr = head; while (listPtr) { DCItem *nextPtr = listPtr->next; - if (listPtr->hDC == hDC) { + if (listPtr->hDC == hDC && listPtr->hWnd == hWnd) { *prevPtrPtr = nextPtr; break; } @@ -7235,9 +7235,9 @@ void DCList::RealizePalettes(int screen) listLock.Leave(); } -void MoveDCToPassiveList(HDC hDC) { +void MoveDCToPassiveList(HDC hDC, HWND hWnd) { DCItem *removedDC; - if ((removedDC = activeDCList.RemoveDC(hDC)) != NULL) { + if ((removedDC = activeDCList.RemoveDC(hDC, hWnd)) != NULL) { passiveDCList.AddDCItem(removedDC); } } diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.h b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.h index 9fe2754142b..f09b41f5b54 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.h +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -900,13 +900,13 @@ public: void AddDC(HDC hDC, HWND hWnd); void AddDCItem(DCItem *newItem); - DCItem *RemoveDC(HDC hDC); + DCItem *RemoveDC(HDC hDC, HWND hWnd); DCItem *RemoveAllDCs(HWND hWnd); void RealizePalettes(int screen); }; void ReleaseDCList(HWND hwnd, DCList &list); -void MoveDCToPassiveList(HDC hDC); +void MoveDCToPassiveList(HDC hDC, HWND hWnd); #include "ObjectList.h" From bfcf012a014ff1ffa356eea85ba437ef06209b35 Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Tue, 20 Oct 2015 22:46:29 +0300 Subject: [PATCH 11/31] 7182758: BMPMetadata returns invalid PhysicalPixelSpacing Reviewed-by: serb, vadim --- .../sun/imageio/plugins/bmp/BMPMetadata.java | 4 +- .../plugins/bmp/BMPPixelSpacingTest.java | 115 ++++++++++++++++++ 2 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 jdk/test/javax/imageio/plugins/bmp/BMPPixelSpacingTest.java diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java index c22415b7575..d955c5f593c 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java @@ -247,11 +247,11 @@ public class BMPMetadata extends IIOMetadata implements BMPConstants { node.appendChild(subNode); subNode = new IIOMetadataNode("HorizontalPhysicalPixelSpacing"); - subNode.setAttribute("value", "" + (1 / xPixelsPerMeter * 1000)); + subNode.setAttribute("value", "" + (1000.0F / xPixelsPerMeter)); node.appendChild(subNode); subNode = new IIOMetadataNode("VerticalPhysicalPixelSpacing"); - subNode.setAttribute("value", "" + (1 / yPixelsPerMeter * 1000)); + subNode.setAttribute("value", "" + (1000.0F / yPixelsPerMeter)); node.appendChild(subNode); return node; diff --git a/jdk/test/javax/imageio/plugins/bmp/BMPPixelSpacingTest.java b/jdk/test/javax/imageio/plugins/bmp/BMPPixelSpacingTest.java new file mode 100644 index 00000000000..7f2c989014f --- /dev/null +++ b/jdk/test/javax/imageio/plugins/bmp/BMPPixelSpacingTest.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 7182758 + * @summary Test verifies whether we are getting correct Horizontal + * & Vertical Physical pixel spacing for active BMP image + * through stored metadata or not. + * @run main BMPPixelSpacingTest + */ + +import java.io.ByteArrayInputStream; +import java.util.Iterator; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.stream.ImageInputStream; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class BMPPixelSpacingTest { + + public static void main(String[] args) throws Exception { + // Header contaning X & Y pixels-per-meter more than value 1 + byte[] bmpHeaderData = { (byte) 0x42, (byte) 0x4d, (byte) 0x7e, + (byte) 0x06, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x3e, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x28, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x64, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x64, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff }; + + ImageInputStream imageInput = ImageIO. + createImageInputStream(new ByteArrayInputStream(bmpHeaderData)); + + for (Iterator it = ImageIO.getImageReaders(imageInput); + it.hasNext(); ) { + ImageReader reader = it.next(); + reader.setInput(imageInput); + IIOMetadata metadata = reader.getImageMetadata(0); + + Node rootNode = metadata.getAsTree("javax_imageio_1.0"); + NodeList nl = rootNode.getChildNodes(); + + //Parse until you get Dimension child node + for (int i = 0; i < nl.getLength(); i++) { + Node node = nl.item(i); + if ((node.getNodeName()).equals("Dimension")) { + //get childnode list under Dimension node + NodeList cl = node.getChildNodes(); + //Corresponding node indices under Dimension node + int horizontalNodeIndex = 1; + int verticalNodeIndex = 2; + Node horizontalNode = cl.item(horizontalNodeIndex); + Node verticalNode = cl.item(verticalNodeIndex); + + //get attributes for horizontal and vertical nodes + NamedNodeMap horizontalAttr = horizontalNode. + getAttributes(); + NamedNodeMap verticalAttr = verticalNode.getAttributes(); + + //since they have only one attribute index is 0 + int attributeIndex = 0; + Node horizontalValue = horizontalAttr.item(attributeIndex); + Node verticalValue = verticalAttr.item(attributeIndex); + float horizontalNodeValue = Float. + parseFloat((horizontalValue.getNodeValue())); + float verticalNodeValue = Float. + parseFloat((verticalValue.getNodeValue())); + + float expectedHorizontalValue, expectedVerticalValue; + // in test metadata xPixelsPerMeter & yPixelsPerMeter is 2 + expectedHorizontalValue = expectedVerticalValue = + 1000.0F / 2; + //expected and returned values should be same + if ((Float.compare(horizontalNodeValue, + expectedHorizontalValue) != 0) || + (Float.compare(verticalNodeValue, + expectedVerticalValue) != 0)) { + throw new RuntimeException("Invalid pixel spacing"); + } + } + } + } + } +} From b96af1d249a237b9f897638f1df78d1d8258840b Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Wed, 21 Oct 2015 18:32:56 +0300 Subject: [PATCH 12/31] 8138764: In some cases the usage of TreeLock can be replaced by other synchronization Reviewed-by: alexp, alexsch --- .../share/classes/java/awt/Component.java | 6 +- .../share/classes/java/awt/Window.java | 20 ++--- .../classes/sun/swing/CachedPainter.java | 22 +---- .../TreeLockDeadlock/TreeLockDeadlock.java | 88 +++++++++++++++++++ 4 files changed, 100 insertions(+), 36 deletions(-) create mode 100644 jdk/test/java/awt/Component/TreeLockDeadlock/TreeLockDeadlock.java diff --git a/jdk/src/java.desktop/share/classes/java/awt/Component.java b/jdk/src/java.desktop/share/classes/java/awt/Component.java index 72c459943b3..1d80c9e01e0 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Component.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Component.java @@ -312,7 +312,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * @see GraphicsConfiguration * @see #getGraphicsConfiguration */ - private transient GraphicsConfiguration graphicsConfig = null; + private transient volatile GraphicsConfiguration graphicsConfig; /** * A reference to a BufferStrategy object @@ -1143,9 +1143,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * @since 1.3 */ public GraphicsConfiguration getGraphicsConfiguration() { - synchronized(getTreeLock()) { - return getGraphicsConfiguration_NoClientCode(); - } + return getGraphicsConfiguration_NoClientCode(); } final GraphicsConfiguration getGraphicsConfiguration_NoClientCode() { diff --git a/jdk/src/java.desktop/share/classes/java/awt/Window.java b/jdk/src/java.desktop/share/classes/java/awt/Window.java index 6f834a3f152..72fee8d1c9c 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Window.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Window.java @@ -347,7 +347,7 @@ public class Window extends Container implements Accessible { * @see #getOpacity() * @since 1.7 */ - private float opacity = 1.0f; + private volatile float opacity = 1.0f; /** * The shape assigned to this window. This field is set to {@code null} if @@ -1040,9 +1040,7 @@ public class Window extends Container implements Accessible { closeSplashScreen(); Dialog.checkShouldBeBlocked(this); super.show(); - synchronized (getTreeLock()) { - this.locationByPlatform = false; - } + locationByPlatform = false; for (int i = 0; i < ownedWindowList.size(); i++) { Window child = ownedWindowList.elementAt(i).get(); if ((child != null) && child.showWithParent) { @@ -1115,9 +1113,7 @@ public class Window extends Container implements Accessible { modalBlocker.unblockWindow(this); } super.hide(); - synchronized (getTreeLock()) { - this.locationByPlatform = false; - } + locationByPlatform = false; } final void clearMostRecentFocusOwnerOnHide() { @@ -3411,7 +3407,7 @@ public class Window extends Container implements Accessible { return super.canContainFocusOwner(focusOwnerCandidate) && isFocusableWindow(); } - private boolean locationByPlatform = locationByPlatformProp; + private volatile boolean locationByPlatform = locationByPlatformProp; /** @@ -3482,9 +3478,7 @@ public class Window extends Container implements Accessible { * @since 1.5 */ public boolean isLocationByPlatform() { - synchronized (getTreeLock()) { - return locationByPlatform; - } + return locationByPlatform; } /** @@ -3573,9 +3567,7 @@ public class Window extends Container implements Accessible { * @since 1.7 */ public float getOpacity() { - synchronized (getTreeLock()) { - return opacity; - } + return opacity; } /** diff --git a/jdk/src/java.desktop/share/classes/sun/swing/CachedPainter.java b/jdk/src/java.desktop/share/classes/sun/swing/CachedPainter.java index ef9a3c2baaf..9e9ca37e912 100644 --- a/jdk/src/java.desktop/share/classes/sun/swing/CachedPainter.java +++ b/jdk/src/java.desktop/share/classes/sun/swing/CachedPainter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,9 +53,7 @@ import java.util.*; */ public abstract class CachedPainter { // CacheMap maps from class to ImageCache. - private static final Map cacheMap = - new HashMap(); - + private static final Map cacheMap = new HashMap<>(); private static ImageCache getCache(Object key) { synchronized(CachedPainter.class) { @@ -96,20 +94,8 @@ public abstract class CachedPainter { if (w <= 0 || h <= 0) { return; } - if (c != null) { - synchronized(c.getTreeLock()) { - synchronized(CachedPainter.class) { - // If c is non-null, synchronize on the tree lock. - // This is necessary because asking for the - // GraphicsConfiguration will grab a tree lock. - paint0(c, g, x, y, w, h, args); - } - } - } - else { - synchronized(CachedPainter.class) { - paint0(c, g, x, y, w, h, args); - } + synchronized (CachedPainter.class) { + paint0(c, g, x, y, w, h, args); } } diff --git a/jdk/test/java/awt/Component/TreeLockDeadlock/TreeLockDeadlock.java b/jdk/test/java/awt/Component/TreeLockDeadlock/TreeLockDeadlock.java new file mode 100644 index 00000000000..91e651cebb9 --- /dev/null +++ b/jdk/test/java/awt/Component/TreeLockDeadlock/TreeLockDeadlock.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Frame; +import java.awt.GraphicsConfiguration; +import java.awt.Window; + +import static java.util.concurrent.TimeUnit.MINUTES; +import static java.util.concurrent.TimeUnit.NANOSECONDS; + +/** + * @test + * @bug 8138764 + */ +public final class TreeLockDeadlock extends Frame { + + @Override + public synchronized GraphicsConfiguration getGraphicsConfiguration() { + return super.getGraphicsConfiguration(); + } + + @Override + public synchronized void reshape(int x, int y, int width, int height) { + super.reshape(x, y, width, height); + } + + @Override + public synchronized float getOpacity() { + return super.getOpacity(); + } + + public static void main(final String[] args) throws Exception { + final Window window = new TreeLockDeadlock(); + window.setSize(300, 300); + test(window); + } + + private static void test(final Window window) throws Exception { + final long start = System.nanoTime(); + final long end = start + NANOSECONDS.convert(1, MINUTES); + + final Runnable r1 = () -> { + while (System.nanoTime() < end) { + window.setBounds(window.getBounds()); + } + }; + final Runnable r2 = () -> { + while (System.nanoTime() < end) { + window.getGraphicsConfiguration(); + window.getOpacity(); + } + }; + + final Thread t1 = new Thread(r1); + final Thread t2 = new Thread(r1); + final Thread t3 = new Thread(r2); + final Thread t4 = new Thread(r2); + + t1.start(); + t2.start(); + t3.start(); + t4.start(); + t1.join(); + t2.join(); + t3.join(); + t4.join(); + } +} From d9ebc2b4c2c47e16b264648bee8dda5fc80d90ee Mon Sep 17 00:00:00 2001 From: Mikhail Cherkasov Date: Wed, 21 Oct 2015 18:58:19 +0300 Subject: [PATCH 13/31] 8136763: [macosx] java always returns only one value for "text/uri-list" dataflavor even if several files were copied Reviewed-by: alexsch, serb --- .../resources/flavormap.properties | 5 +- .../sun/lwawt/macosx/CDataTransferer.java | 72 +++++++++---------- .../MacOsXFileAndMultipleFileCopingTest.java} | 57 ++++++++++----- 3 files changed, 75 insertions(+), 59 deletions(-) rename jdk/test/java/awt/datatransfer/DataFlavor/{XJavaUrlDataFlavorTest/XJavaUrlDataFlavorTest.java => MacOsXFileAndMultipleFileCopingTest/MacOsXFileAndMultipleFileCopingTest.java} (85%) diff --git a/jdk/src/java.datatransfer/macosx/classes/sun/datatransfer/resources/flavormap.properties b/jdk/src/java.datatransfer/macosx/classes/sun/datatransfer/resources/flavormap.properties index 10d625fc494..370c7de21fb 100644 --- a/jdk/src/java.datatransfer/macosx/classes/sun/datatransfer/resources/flavormap.properties +++ b/jdk/src/java.datatransfer/macosx/classes/sun/datatransfer/resources/flavormap.properties @@ -72,6 +72,7 @@ JFIF=image/x-java-image;class=java.awt.Image TIFF=image/x-java-image;class=java.awt.Image RICH_TEXT=text/rtf HTML=text/html;charset=utf-8;eoln="\r\n";terminators=1 -URL=application/x-java-url;class=java.net.URL,\ - text/uri-list;eoln="\r\n";terminators=1 +URL=application/x-java-url;class=java.net.URL +FILE_NAME=text/uri-list;eoln="\r\n";terminators=1 +URL=text/uri-list;eoln="\r\n";terminators=1 XPICT=image/x-pict;class=java.io.InputStream diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java index ae1d4446c05..3f05185c091 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java @@ -1,3 +1,4 @@ + /* * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -28,12 +29,13 @@ package sun.lwawt.macosx; import java.awt.*; import java.io.*; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import java.nio.charset.Charset; import java.text.Normalizer; import java.text.Normalizer.Form; import java.util.*; -import java.util.regex.*; import java.awt.datatransfer.*; import sun.awt.datatransfer.*; @@ -127,51 +129,33 @@ public class CDataTransferer extends DataTransferer { long format, Transferable transferable) throws IOException { if (format == CF_URL && URL.class.equals(flavor.getRepresentationClass())) { - String charset = Charset.defaultCharset().name(); - if (transferable != null && transferable.isDataFlavorSupported(javaTextEncodingFlavor)) { - try { - charset = new String((byte[]) transferable.getTransferData(javaTextEncodingFlavor), "UTF-8"); - } catch (UnsupportedFlavorException cannotHappen) { - } + String[] strings = dragQueryFile(bytes); + if(strings == null || strings.length == 0) { + return null; } - String xml = new String(bytes, charset); - // macosx pasteboard returns a property list that consists of one URL - // let's extract it. - return new URL(extractURL(xml)); - } - - if (format == CF_STRING) { + return new URL(strings[0]); + } else if(isUriListFlavor(flavor)) { + // dragQueryFile works fine with files and url, + // it parses and extracts values from property list. + // maxosx always returns property list for + // CF_URL and CF_FILE + String[] strings = dragQueryFile(bytes); + if(strings == null) { + return null; + } + bytes = String.join(System.getProperty("line.separator"), + strings).getBytes(); + // now we extracted uri from xml, now we should treat it as + // regular string that allows to translate data to target represantation + // class by base method + format = CF_STRING; + } else if (format == CF_STRING) { bytes = Normalizer.normalize(new String(bytes, "UTF8"), Form.NFC).getBytes("UTF8"); } return super.translateBytes(bytes, flavor, format, transferable); } - /** - * Macosx pasteboard returns xml document that contains one URL, for exmple: - *
    -     *     {@code
    -     * 
    -     * 
    -     * 
    -     *      
    -     *          file:///path_to_file
    -     *          
    -     *      
    -     * 
    -     *     }
    -     * 
    - */ - private String extractURL(String xml) { - Pattern urlExtractorPattern = Pattern.compile("(.*)"); - Matcher matcher = urlExtractorPattern.matcher(xml); - if (matcher.find()) { - return matcher.group(1); - } else { - return null; - } - } - @Override protected synchronized Long getFormatForNativeAsLong(String str) { Long format = predefinedClipboardNameMap.get(str); @@ -247,6 +231,7 @@ public class CDataTransferer extends DataTransferer { return nativeDragQueryFile(bytes); } + @Override protected Image platformImageBytesToImage(byte[] bytes, long format) throws IOException { return CImage.getCreator().createImageFromPlatformImageBytes(bytes); @@ -271,7 +256,7 @@ public class CDataTransferer extends DataTransferer { } try { DataFlavor df = new DataFlavor(nat); - if (df.getPrimaryType().equals("text") && df.getSubType().equals("uri-list")) { + if (isUriListFlavor(df)) { return true; } } catch (Exception e) { @@ -279,4 +264,11 @@ public class CDataTransferer extends DataTransferer { } return false; } + + private boolean isUriListFlavor(DataFlavor df) { + if (df.getPrimaryType().equals("text") && df.getSubType().equals("uri-list")) { + return true; + } + return false; + } } diff --git a/jdk/test/java/awt/datatransfer/DataFlavor/XJavaUrlDataFlavorTest/XJavaUrlDataFlavorTest.java b/jdk/test/java/awt/datatransfer/DataFlavor/MacOsXFileAndMultipleFileCopingTest/MacOsXFileAndMultipleFileCopingTest.java similarity index 85% rename from jdk/test/java/awt/datatransfer/DataFlavor/XJavaUrlDataFlavorTest/XJavaUrlDataFlavorTest.java rename to jdk/test/java/awt/datatransfer/DataFlavor/MacOsXFileAndMultipleFileCopingTest/MacOsXFileAndMultipleFileCopingTest.java index 7e86b92e192..18b70121aab 100644 --- a/jdk/test/java/awt/datatransfer/DataFlavor/XJavaUrlDataFlavorTest/XJavaUrlDataFlavorTest.java +++ b/jdk/test/java/awt/datatransfer/DataFlavor/MacOsXFileAndMultipleFileCopingTest/MacOsXFileAndMultipleFileCopingTest.java @@ -23,10 +23,9 @@ /* @test - @bug 8081787 - @summary MalformedURLException is thrown during reading data for application/x-java-url;class=java.net.URL flavor + @bug 8081787 8136763 @author Mikhail Cherkasov - @run main/manual XJavaUrlDataFlavorTest + @run main/manual MacOsXFileAndMultipleFileCopingTest */ import javax.swing.*; @@ -36,17 +35,24 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.net.URL; -public class XJavaUrlDataFlavorTest { +public class MacOsXFileAndMultipleFileCopingTest { private static void init() { String[] instructions = {"Test for MacOS X only:", "1. The aim is to test that java works fine with \"application/" + - "x-java-url;class=java.net.URL\"falvor.", + "x-java-url;class=java.net.URL\"falvor and support coping of multiple files", "2. Open finder and select any file.", "3. Press CMD+C or press \"Copy\" in context menu", - "4. Focus window with \"Test\" Button.", + "4. Focus window with \"Test URL\" Button.", "5. If you see URL for selected file, then test PASSED,", - "otherwise test FAILED." + "otherwise test FAILED.", + + "6. Open finder again and select several files.", + "7. Press CMD+C or press \"Copy\" in context menu", + "8. Focus window with \"Test multiple files coping\" Button.", + "9. If you see list of selected files, then test PASSED,", + "otherwise test FAILED.", + }; Sysout.createDialog(); @@ -57,22 +63,36 @@ public class XJavaUrlDataFlavorTest { panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS)); frame.add(panel); - Button testButton = new Button("Test"); - final TextField textField = new TextField(40); - testButton.addActionListener(new AbstractAction() { + Button testUrlBtn = new Button("Test URL"); + final TextArea textArea = new TextArea(5, 80); + testUrlBtn.addActionListener(new AbstractAction() { @Override public void actionPerformed(ActionEvent ae) { try { Clipboard board = Toolkit.getDefaultToolkit().getSystemClipboard(); - URL url = (URL)board.getData(new DataFlavor("application/x-java-url;class=java.net.URL")); - textField.setText(url.toString()); + URL url = (URL) board.getData(new DataFlavor("application/x-java-url;class=java.net.URL")); + textArea.setText(url.toString()); } catch (Exception e) { throw new RuntimeException(e); } } }); - panel.add(testButton); - panel.add(textField); + panel.add(testUrlBtn); + Button testUriList = new Button("Test multiple files coping"); + testUriList.addActionListener(new AbstractAction() { + @Override + public void actionPerformed(ActionEvent ae) { + try { + Clipboard board = Toolkit.getDefaultToolkit().getSystemClipboard(); + String files = (String) board.getData(new DataFlavor("text/uri-list;class=java.lang.String")); + textArea.setText(files); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + panel.add(testUriList); + panel.add(textArea); frame.setBounds(200, 200, 400, 400); frame.setVisible(true); @@ -100,6 +120,9 @@ public class XJavaUrlDataFlavorTest { private static int sleepTime = 300000; public static void main(String args[]) throws InterruptedException { + if (!System.getProperty("os.name").startsWith("Mac")) { + return; + } mainThread = Thread.currentThread(); try { init(); @@ -336,10 +359,10 @@ class TestDialog extends Dialog implements ActionListener { //ManualMainTest public void actionPerformed(ActionEvent e) { if (e.getActionCommand() == "pass") { - XJavaUrlDataFlavorTest.pass(); + MacOsXFileAndMultipleFileCopingTest.pass(); } else { - XJavaUrlDataFlavorTest.fail(); + MacOsXFileAndMultipleFileCopingTest.fail(); } } -}// TestDialog class +}// TestDialog class \ No newline at end of file From 5c2672351683467fdeeda7796d971634fc3c51ae Mon Sep 17 00:00:00 2001 From: Phil Race Date: Wed, 21 Oct 2015 09:21:25 -0700 Subject: [PATCH 14/31] 8132890: Text overlapping on dot matrix printers Reviewed-by: jgodinez, serb --- .../sun/awt/windows/WPathGraphics.java | 85 ++++++++++++++----- .../awt/print/PrinterJob/PrintTextTest.java | 52 +++++++++++- 2 files changed, 116 insertions(+), 21 deletions(-) diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java index 75e51636ec2..f892a88bf6c 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java @@ -494,24 +494,48 @@ final class WPathGraphics extends PathGraphics { */ float fontSize = font.getSize2D(); + double devResX = wPrinterJob.getXRes(); + double devResY = wPrinterJob.getYRes(); + + double fontDevScaleY = devResY / DEFAULT_USER_RES; + + int orient = getPageFormat().getOrientation(); + if (orient == PageFormat.LANDSCAPE || + orient == PageFormat.REVERSE_LANDSCAPE) + { + double tmp = devResX; + devResX = devResY; + devResY = tmp; + } + + double devScaleX = devResX / DEFAULT_USER_RES; + double devScaleY = devResY / DEFAULT_USER_RES; + fontTransform.scale(1.0/devScaleX, 1.0/devScaleY); + Point2D.Double pty = new Point2D.Double(0.0, 1.0); fontTransform.deltaTransform(pty, pty); double scaleFactorY = Math.sqrt(pty.x*pty.x+pty.y*pty.y); - float scaledFontSizeY = (float)(fontSize * scaleFactorY); + float scaledFontSizeY = (float)(fontSize * scaleFactorY * fontDevScaleY); Point2D.Double ptx = new Point2D.Double(1.0, 0.0); fontTransform.deltaTransform(ptx, ptx); double scaleFactorX = Math.sqrt(ptx.x*ptx.x+ptx.y*ptx.y); - float scaledFontSizeX = (float)(fontSize * scaleFactorX); float awScale = getAwScale(scaleFactorX, scaleFactorY); int iangle = getAngle(ptx); + ptx = new Point2D.Double(1.0, 0.0); + deviceTransform.deltaTransform(ptx, ptx); + double advanceScaleX = Math.sqrt(ptx.x*ptx.x+ptx.y*ptx.y); + pty = new Point2D.Double(0.0, 1.0); + deviceTransform.deltaTransform(pty, pty); + double advanceScaleY = Math.sqrt(pty.x*pty.x+pty.y*pty.y); + Font2D font2D = FontUtilities.getFont2D(font); if (font2D instanceof TrueTypeFont) { textOut(str, font, (TrueTypeFont)font2D, frc, scaledFontSizeY, iangle, awScale, - deviceTransform, scaleFactorX, + advanceScaleX, advanceScaleY, x, y, devpos.x, devpos.y, targetW); } else if (font2D instanceof CompositeFont) { /* Composite fonts are made up of multiple fonts and each @@ -542,7 +566,7 @@ final class WPathGraphics extends PathGraphics { PhysicalFont slotFont = compFont.getSlotFont(slot); textOut(substr, font, slotFont, frc, scaledFontSizeY, iangle, awScale, - deviceTransform, scaleFactorX, + advanceScaleX, advanceScaleY, userx, usery, devx, devy, 0f); Rectangle2D bds = font.getStringBounds(substr, frc); float xAdvance = (float)bds.getWidth(); @@ -635,18 +659,42 @@ final class WPathGraphics extends PathGraphics { */ float fontSize = font.getSize2D(); + double devResX = wPrinterJob.getXRes(); + double devResY = wPrinterJob.getYRes(); + + double fontDevScaleY = devResY / DEFAULT_USER_RES; + + int orient = getPageFormat().getOrientation(); + if (orient == PageFormat.LANDSCAPE || + orient == PageFormat.REVERSE_LANDSCAPE) + { + double tmp = devResX; + devResX = devResY; + devResY = tmp; + } + + double devScaleX = devResX / DEFAULT_USER_RES; + double devScaleY = devResY / DEFAULT_USER_RES; + fontTransform.scale(1.0/devScaleX, 1.0/devScaleY); + Point2D.Double pty = new Point2D.Double(0.0, 1.0); fontTransform.deltaTransform(pty, pty); double scaleFactorY = Math.sqrt(pty.x*pty.x+pty.y*pty.y); - float scaledFontSizeY = (float)(fontSize * scaleFactorY); + float scaledFontSizeY = (float)(fontSize * scaleFactorY * fontDevScaleY); - Point2D.Double pt = new Point2D.Double(1.0, 0.0); - fontTransform.deltaTransform(pt, pt); - double scaleFactorX = Math.sqrt(pt.x*pt.x+pt.y*pt.y); - float scaledFontSizeX = (float)(fontSize * scaleFactorX); + Point2D.Double ptx = new Point2D.Double(1.0, 0.0); + fontTransform.deltaTransform(ptx, ptx); + double scaleFactorX = Math.sqrt(ptx.x*ptx.x+ptx.y*ptx.y); float awScale = getAwScale(scaleFactorX, scaleFactorY); - int iangle = getAngle(pt); + int iangle = getAngle(ptx); + + ptx = new Point2D.Double(1.0, 0.0); + deviceTransform.deltaTransform(ptx, ptx); + double advanceScaleX = Math.sqrt(ptx.x*ptx.x+ptx.y*ptx.y); + pty = new Point2D.Double(0.0, 1.0); + deviceTransform.deltaTransform(pty, pty); + double advanceScaleY = Math.sqrt(pty.x*pty.x+pty.y*pty.y); int numGlyphs = gv.getNumGlyphs(); int[] glyphCodes = gv.getGlyphCodes(0, numGlyphs, null); @@ -705,8 +753,7 @@ final class WPathGraphics extends PathGraphics { * rotation element of the deviceTransform. */ AffineTransform advanceTransform = - new AffineTransform(deviceTransform); - advanceTransform.rotate(iangle*Math.PI/1800.0); + AffineTransform.getScaleInstance(advanceScaleX, advanceScaleY); float[] glyphAdvPos = new float[glyphPos.length]; advanceTransform.transform(glyphPos, 0, //source @@ -784,8 +831,7 @@ final class WPathGraphics extends PathGraphics { Font font, PhysicalFont font2D, FontRenderContext frc, float deviceSize, int rotation, float awScale, - AffineTransform deviceTransform, - double scaleFactorX, + double scaleFactorX, double scaleFactorY, float userx, float usery, float devx, float devy, float targetW) { @@ -826,8 +872,7 @@ final class WPathGraphics extends PathGraphics { * See earlier comment in printGlyphVector() for details. */ AffineTransform advanceTransform = - new AffineTransform(deviceTransform); - advanceTransform.rotate(rotation*Math.PI/1800.0); + AffineTransform.getScaleInstance(scaleFactorX, scaleFactorY); float[] glyphAdvPos = new float[glyphPos.length]; advanceTransform.transform(glyphPos, 0, //source @@ -841,11 +886,11 @@ final class WPathGraphics extends PathGraphics { /* If 2D and GDI agree on the advance of the string we do not * need to explicitly assign glyph positions. * If we are to use the GDI advance, require it to agree with - * JDK to a precision of <= 0.2% - ie 1 pixel in 500 + * JDK to a precision of <= 1.0% - ie 1 pixel in 100 * discrepancy after rounding the 2D advance to the * nearest pixel and is greater than one pixel in total. - * ie strings < 500 pixels in length will be OK so long - * as they differ by only 1 pixel even though that is > 0.02% + * ie strings < 100 pixels in length will be OK so long + * as they differ by only 1 pixel even though that is > 1% * The bounds from 2D are in user space so need to * be scaled to device space for comparison with GDI. * scaleX is the scale from user space to device space needed for this. @@ -863,7 +908,7 @@ final class WPathGraphics extends PathGraphics { if (ratio < 1) { ratio = 1/ratio; } - return diff <= 1 || ratio < 1.002; + return diff <= 1 || ratio < 1.01; } return true; } diff --git a/jdk/test/java/awt/print/PrinterJob/PrintTextTest.java b/jdk/test/java/awt/print/PrinterJob/PrintTextTest.java index 6b58454318d..6ad45dd6f4f 100644 --- a/jdk/test/java/awt/print/PrinterJob/PrintTextTest.java +++ b/jdk/test/java/awt/print/PrinterJob/PrintTextTest.java @@ -23,7 +23,7 @@ /** * @test - * @bug 6425068 7157659 + * @bug 6425068 7157659 8132890 * @summary Confirm that text prints where we expect to the length we expect. * @run main/manual=yesno PrintTextTest */ @@ -113,6 +113,32 @@ public class PrintTextTest extends Component implements Printable { book.append(ptt, portrait); book.append(ptt, landscape); + font = new Font("Dialog", Font.PLAIN, 18); + AffineTransform scaleTx = AffineTransform.getScaleInstance(1.25, 1.25); + name = "Page " + new Integer(page++); + ptt = new PrintTextTest(name, font, scaleTx, false); + p.add(name, ptt); + book.append(ptt, portrait); + book.append(ptt, landscape); + + font = new Font("Dialog", Font.PLAIN, 18); + scaleTx = AffineTransform.getScaleInstance(-1.25, 1.25); + scaleTx.translate(-preferredSize/1.25, 0); + name = "Page " + new Integer(page++); + ptt = new PrintTextTest(name, font, scaleTx, false); + p.add(name, ptt); + book.append(ptt, portrait); + book.append(ptt, landscape); + + font = new Font("Dialog", Font.PLAIN, 18); + scaleTx = AffineTransform.getScaleInstance(1.25, -1.25); + scaleTx.translate(0, -preferredSize/1.25); + name = "Page " + new Integer(page++); + ptt = new PrintTextTest(name, font, scaleTx, false); + p.add(name, ptt); + book.append(ptt, portrait); + book.append(ptt, landscape); + font = font.deriveFont(rotTx); name = "Page " + new Integer(page++); ptt = new PrintTextTest(name, font, null, false); @@ -121,6 +147,30 @@ public class PrintTextTest extends Component implements Printable { book.append(ptt, portrait); book.append(ptt, landscape); + font = new Font("Monospaced", Font.PLAIN, 12); + name = "Page " + new Integer(page++); + ptt = new PrintTextTest(name, font, null, false); + p.add(ptt, BorderLayout.CENTER); + p.add(name, ptt); + book.append(ptt, portrait); + book.append(ptt, landscape); + + Font xfont = font.deriveFont(AffineTransform.getScaleInstance(1.5, 1)); + name = "Page " + new Integer(page++); + ptt = new PrintTextTest(name, xfont, null, false); + p.add(ptt, BorderLayout.CENTER); + p.add(name, ptt); + book.append(ptt, portrait); + book.append(ptt, landscape); + + Font yfont = font.deriveFont(AffineTransform.getScaleInstance(1, 1.5)); + name = "Page " + new Integer(page++); + ptt = new PrintTextTest(name, yfont, null, false); + p.add(ptt, BorderLayout.CENTER); + p.add(name, ptt); + book.append(ptt, portrait); + book.append(ptt, landscape); + if (System.getProperty("os.name").startsWith("Windows")) { font = new Font("MS Gothic", Font.PLAIN, 12); name = "Page " + new Integer(page++); From 9a971332651ee29b10defb696fe09feeb4829ed6 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Wed, 21 Oct 2015 21:28:59 +0300 Subject: [PATCH 15/31] 8041900: [macosx] Java forces the use of discrete GPU Reviewed-by: ssadetsky, alexsch --- .../native/libawt_lwawt/awt/CGraphicsEnv.m | 24 +++++++++++-------- .../java2d/opengl/CGLGraphicsConfig.m | 1 + 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsEnv.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsEnv.m index 745569452d6..1c3baf40dde 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsEnv.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsEnv.m @@ -26,6 +26,7 @@ #import "AWT_debug.h" #import "jni_util.h" +#import "ThreadUtilities.h" #import @@ -114,17 +115,20 @@ static void displaycb_handle { if (flags == kCGDisplayBeginConfigurationFlag) return; - JNFPerformEnvBlock(JNFThreadDetachImmediately, ^(JNIEnv *env) { - JNFWeakJObjectWrapper *wrapper = (JNFWeakJObjectWrapper *)userInfo; + [ThreadUtilities performOnMainThreadWaiting:NO block:^() { - jobject graphicsEnv = [wrapper jObjectWithEnv:env]; - if (graphicsEnv == NULL) return; // ref already GC'd - static JNF_CLASS_CACHE(jc_CGraphicsEnvironment, "sun/awt/CGraphicsEnvironment"); - static JNF_MEMBER_CACHE(jm_displayReconfiguration, jc_CGraphicsEnvironment, "_displayReconfiguration", "(IZ)V"); - JNFCallVoidMethod(env, graphicsEnv, jm_displayReconfiguration, - (jint) display, - (jboolean) flags & kCGDisplayRemoveFlag); - }); + JNFPerformEnvBlock(JNFThreadDetachImmediately, ^(JNIEnv *env) { + JNFWeakJObjectWrapper *wrapper = (JNFWeakJObjectWrapper *)userInfo; + + jobject graphicsEnv = [wrapper jObjectWithEnv:env]; + if (graphicsEnv == NULL) return; // ref already GC'd + static JNF_CLASS_CACHE(jc_CGraphicsEnvironment, "sun/awt/CGraphicsEnvironment"); + static JNF_MEMBER_CACHE(jm_displayReconfiguration, + jc_CGraphicsEnvironment, "_displayReconfiguration","(IZ)V"); + JNFCallVoidMethod(env, graphicsEnv, jm_displayReconfiguration, + (jint) display, (jboolean) flags & kCGDisplayRemoveFlag); + }); + }]; } /* diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLGraphicsConfig.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLGraphicsConfig.m index 605c345f2ce..775b92f5b2b 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLGraphicsConfig.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLGraphicsConfig.m @@ -233,6 +233,7 @@ Java_sun_java2d_opengl_CGLGraphicsConfig_getCGLConfigInfo } NSOpenGLPixelFormatAttribute attrs[] = { + NSOpenGLPFAAllowOfflineRenderers, NSOpenGLPFAClosestPolicy, NSOpenGLPFAWindow, NSOpenGLPFAPixelBuffer, From 80a6875dbf751a7d089cff7381ada3ac3e297693 Mon Sep 17 00:00:00 2001 From: Sebastian Sickelmann Date: Thu, 22 Oct 2015 13:46:52 +0400 Subject: [PATCH 16/31] 8139754: Change Boolean constructor use to the use of Boolean factorymethods. For the macosx-port-dev area Reviewed-by: serb, alexsch --- .../macosx/classes/com/apple/laf/AquaTabbedPaneUI.java | 2 +- .../macosx/classes/sun/lwawt/macosx/CAccessibility.java | 2 +- .../macosx/classes/sun/lwawt/macosx/LWCToolkit.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java index b07ab5ab066..f5c8cd1bcf0 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java @@ -845,7 +845,7 @@ public class AquaTabbedPaneUI extends AquaTabbedPaneCopyFromBasicUI { boolean isDefaultFocusReceiver(final JComponent component) { if (isDefaultFocusReceiver == null) { Component defaultFocusReceiver = KeyboardFocusManager.getCurrentKeyboardFocusManager().getDefaultFocusTraversalPolicy().getDefaultComponent(getTopLevelFocusCycleRootAncestor(component)); - isDefaultFocusReceiver = new Boolean(defaultFocusReceiver != null && defaultFocusReceiver.equals(component)); + isDefaultFocusReceiver = defaultFocusReceiver != null && defaultFocusReceiver.equals(component); } return isDefaultFocusReceiver.booleanValue(); } diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java index 919c31cb234..3bf3cf8f44e 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java @@ -175,7 +175,7 @@ class CAccessibility implements PropertyChangeListener { final AccessibleSelection as = ac.getAccessibleSelection(); if (as == null) return Boolean.FALSE; - return new Boolean(as.isAccessibleChildSelected(index)); + return as.isAccessibleChildSelected(index); } }, c); } diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index eccba3032dd..8f9e1459103 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -380,7 +380,7 @@ public final class LWCToolkit extends LWToolkit { desktopProperties.put("DnD.Autoscroll.interval", new Integer(50)); desktopProperties.put("DnD.Autoscroll.cursorHysteresis", new Integer(5)); - desktopProperties.put("DnD.isDragImageSupported", new Boolean(true)); + desktopProperties.put("DnD.isDragImageSupported", Boolean.TRUE); // Register DnD cursors desktopProperties.put("DnD.Cursor.CopyDrop", new NamedCursor("DnD.Cursor.CopyDrop")); From 4671194aaf2c20c56a1c55f2ef8c5e4b27301ce6 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Tue, 3 Nov 2015 16:15:52 +0100 Subject: [PATCH 17/31] 6512052: Remove java-rmi.exe and java-rmi.cgi Reviewed-by: alanb --- jdk/make/launcher/Launcher-java.rmi.gmk | 31 ---------- jdk/src/java.rmi/unix/bin/java-rmi.cgi.sh | 74 ----------------------- 2 files changed, 105 deletions(-) delete mode 100644 jdk/src/java.rmi/unix/bin/java-rmi.cgi.sh diff --git a/jdk/make/launcher/Launcher-java.rmi.gmk b/jdk/make/launcher/Launcher-java.rmi.gmk index 26f9b7dc627..58b2328713e 100644 --- a/jdk/make/launcher/Launcher-java.rmi.gmk +++ b/jdk/make/launcher/Launcher-java.rmi.gmk @@ -30,34 +30,3 @@ $(eval $(call SetupLauncher,rmid, \ $(eval $(call SetupLauncher,rmiregistry, \ -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.rmi.registry.RegistryImpl"$(COMMA) }')) - -########################################################################################## - -# -# The java-rmi.cgi script in bin/ only gets delivered in certain situations -# -JAVA_RMI_CGI := $(SUPPORT_OUTPUTDIR)/modules_cmds/$(MODULE)/java-rmi.cgi -ifeq ($(OPENJDK_TARGET_OS), linux) - TARGETS += $(JAVA_RMI_CGI) -endif -ifeq ($(OPENJDK_TARGET_OS), solaris) - TARGETS += $(JAVA_RMI_CGI) -endif - -# TODO: -# On windows java-rmi.cgi shouldn't be bundled since Java 1.2, but has been built all -# this time anyway. Since jdk6, it has been built from the wrong source and resulted -# in a (almost) copy of the standard java launcher named "java-rmi.exe" ending up in -# the final images bin dir. This weird behavior is mimicked here in the converted -# makefiles for now. Should probably just be deleted. -# http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6512052 -ifeq ($(OPENJDK_TARGET_OS), windows) - $(eval $(call SetupLauncher,java-rmi, , \ - $(call SET_SHARED_LIBRARY_MAPFILE,$(JDK_TOPDIR)/make/java/main/java/mapfile-$(OPENJDK_TARGET_CPU)),,,,,,,,,RMI)) -else - $(JAVA_RMI_CGI): $(JDK_TOPDIR)/src/java.rmi/unix/bin/java-rmi.cgi.sh - $(call install-file) - $(CHMOD) a+x $@ -endif - -########################################################################################## diff --git a/jdk/src/java.rmi/unix/bin/java-rmi.cgi.sh b/jdk/src/java.rmi/unix/bin/java-rmi.cgi.sh deleted file mode 100644 index f5d00feac55..00000000000 --- a/jdk/src/java.rmi/unix/bin/java-rmi.cgi.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/sh - -# -# Copyright (c) 1996, 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. -# - -# -# - -# -# This script executes the Java interpreter, defines properties -# that correspond to the CGI 1.0 environment variables, and executes -# the class "sun.rmi.transport.proxy.CGIHandler". It should be -# installed in the directory to which the HTTP server maps the -# URL path "/cgi-bin". -# -# (Configuration is necessary as noted below.) -# -# This class will support a QUERY_STRING of the form "forward=" -# with a REQUEST_METHOD "POST". The body of the request will be -# forwarded (as another POST request) to the server listening on the -# specified port (must be >= 1024). The response from this forwarded -# request will be the response to the original request. -# -# CONFIGURATION: -# -# Fill in correct absolute path to Java interpreter below. For example, -# the "PATH=" line might be changed to the follow if the JDK is installed -# at the path "/home/peter/java": -# -# PATH=/home/peter/java/bin:$PATH -# -PATH=/usr/local/java/bin:$PATH -exec java \ - -DAUTH_TYPE="$AUTH_TYPE" \ - -DCONTENT_LENGTH="$CONTENT_LENGTH" \ - -DCONTENT_TYPE="$CONTENT_TYPE" \ - -DGATEWAY_INTERFACE="$GATEWAY_INTERFACE" \ - -DHTTP_ACCEPT="$HTTP_ACCEPT" \ - -DPATH_INFO="$PATH_INFO" \ - -DPATH_TRANSLATED="$PATH_TRANSLATED" \ - -DQUERY_STRING="$QUERY_STRING" \ - -DREMOTE_ADDR="$REMOTE_ADDR" \ - -DREMOTE_HOST="$REMOTE_HOST" \ - -DREMOTE_IDENT="$REMOTE_IDENT" \ - -DREMOTE_USER="$REMOTE_USER" \ - -DREQUEST_METHOD="$REQUEST_METHOD" \ - -DSCRIPT_NAME="$SCRIPT_NAME" \ - -DSERVER_NAME="$SERVER_NAME" \ - -DSERVER_PORT="$SERVER_PORT" \ - -DSERVER_PROTOCOL="$SERVER_PROTOCOL" \ - -DSERVER_SOFTWARE="$SERVER_SOFTWARE" \ - sun.rmi.transport.proxy.CGIHandler From 937b5e1d5e77c7d2da1b359e1a124f1e05abcdca Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Tue, 3 Nov 2015 10:20:14 -0500 Subject: [PATCH 18/31] 8139345: java/lang/ProcessHandle/TreeTest.java test fails with ... Wrong number of children expected [3] but found [2] Reviewed-by: darcy --- .../java/lang/ProcessHandle/TreeTest.java | 70 +++++++++++++++++-- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/jdk/test/java/lang/ProcessHandle/TreeTest.java b/jdk/test/java/lang/ProcessHandle/TreeTest.java index b41f3c276af..ea12d3f361f 100644 --- a/jdk/test/java/lang/ProcessHandle/TreeTest.java +++ b/jdk/test/java/lang/ProcessHandle/TreeTest.java @@ -27,9 +27,11 @@ import java.util.ArrayList; import java.time.Duration; import java.time.Instant; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -44,6 +46,7 @@ import org.testng.annotations.Test; * @library /lib/testlibrary * Test counting and JavaChild.spawning and counting of Processes. * @run testng/othervm InfoTest + * @key intermittent * @author Roger Riggs */ public class TreeTest extends ProcessUtil { @@ -195,7 +198,7 @@ public class TreeTest extends ProcessUtil { allChildren.stream().map(p -> p.getPid()) .collect(Collectors.toList())); - // Verify that all spawned children show up in the allChildrenList + // Verify that all spawned children show up in the allChildren List processes.forEach((p, parent) -> { Assert.assertEquals(p.isAlive(), true, "Child should be alive: " + p); Assert.assertTrue(allChildren.contains(p), "Spawned child should be listed in allChildren: " + p); @@ -241,6 +244,7 @@ public class TreeTest extends ProcessUtil { printf(" p1: %s%n", p1.getPid()); int newChildren = 3; + CountDownLatch spawnCount = new CountDownLatch(newChildren); // Spawn children and have them wait p1.sendAction("spawn", newChildren, "stdin"); @@ -251,11 +255,26 @@ public class TreeTest extends ProcessUtil { Long child = Long.valueOf(split[2]); Long parent = Long.valueOf(split[0].split(":")[0]); processes.put(ProcessHandle.of(child).get(), ProcessHandle.of(parent).get()); + spawnCount.countDown(); } }); - // Wait for the new processes and save the list - List allChildren = waitForAllChildren(p1Handle, newChildren); + // Wait for all the subprocesses to be listed as started + Assert.assertTrue(spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS), + "Timeout waiting for processes to start"); + + // Debugging; list allChildren that are not expected in processes + List allChildren = ProcessUtil.getAllChildren(p1Handle); + long count = allChildren.stream() + .filter(ph -> !processes.containsKey(ph)) + .count(); + if (count > 0) { + allChildren.stream() + .filter(ph -> !processes.containsKey(ph)) + .forEach(ph1 -> ProcessUtil.printProcess(ph1, "Extra process: ")); + ProcessUtil.logTaskList(); + Assert.assertEquals(0, count, "Extra processes in allChildren"); + } // Verify that all spawned children are alive, show up in the allChildren list // then destroy them @@ -266,6 +285,7 @@ public class TreeTest extends ProcessUtil { }); Assert.assertEquals(processes.size(), newChildren, "Wrong number of children"); + // Wait for each of the processes to exit processes.forEach((p, parent) -> { for (long retries = Utils.adjustTimeout(100L); retries > 0 ; retries--) { if (!p.isAlive()) { @@ -285,8 +305,10 @@ public class TreeTest extends ProcessUtil { p1.destroyForcibly(); p1.waitFor(); + // Verify that none of the spawned children are still listed by allChildren List remaining = getAllChildren(self); - remaining = remaining.stream().filter(processes::contains).collect(Collectors.toList()); + Assert.assertFalse(remaining.remove(p1Handle), "Child p1 should have exited"); + remaining = remaining.stream().filter(processes::containsKey).collect(Collectors.toList()); Assert.assertEquals(remaining.size(), 0, "Subprocess(es) should have exited: " + remaining); } catch (IOException ioe) { @@ -354,6 +376,8 @@ public class TreeTest extends ProcessUtil { */ @Test public static void test5() { + ConcurrentHashMap processes = new ConcurrentHashMap<>(); + int factor = 2; JavaChild p1 = null; Instant start = Instant.now(); @@ -374,11 +398,39 @@ public class TreeTest extends ProcessUtil { p1.sendAction("child", "child", "spawn", factor, "stdin"); int newChildren = factor * (1 + factor * (1 + factor)); - List children = ProcessUtil.waitForAllChildren(p1Handle, newChildren); + CountDownLatch spawnCount = new CountDownLatch(newChildren); + + // Gather the PIDs from the output of the spawning process + p1.forEachOutputLine((s) -> { + String[] split = s.trim().split(" "); + if (split.length == 3 && split[1].equals("spawn")) { + Long child = Long.valueOf(split[2]); + Long parent = Long.valueOf(split[0].split(":")[0]); + processes.put(ProcessHandle.of(child).get(), ProcessHandle.of(parent).get()); + spawnCount.countDown(); + } + }); + + // Wait for all the subprocesses to be listed as started + Assert.assertTrue(spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS), + "Timeout waiting for processes to start"); + + // Debugging; list allChildren that are not expected in processes + List allChildren = ProcessUtil.getAllChildren(p1Handle); + long count = allChildren.stream() + .filter(ph -> !processes.containsKey(ph)) + .count(); + if (count > 0) { + allChildren.stream() + .filter(ph -> !processes.containsKey(ph)) + .forEach(ph1 -> ProcessUtil.printProcess(ph1, "Extra process: ")); + ProcessUtil.logTaskList(); + Assert.assertEquals(0, count, "Extra processes in allChildren"); + } Assert.assertEquals(getChildren(p1Handle).size(), factor, "expected direct children"); - long count = getAllChildren(p1Handle).size(); + count = getAllChildren(p1Handle).size(); long totalChildren = factor * factor * factor + factor * factor + factor; Assert.assertTrue(count >= totalChildren, "expected at least " + totalChildren + ", actual: " + count); @@ -397,6 +449,12 @@ public class TreeTest extends ProcessUtil { if (p1 != null) { p1.destroyForcibly(); } + processes.forEach((p, parent) -> { + if (p.isAlive()) { + ProcessUtil.printProcess(p, "Process Cleanup: "); + p.destroyForcibly(); + } + }); } } From 3449e253b899ed5298e65b6c4c60891565f2b3eb Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Tue, 3 Nov 2015 17:48:19 +0100 Subject: [PATCH 19/31] 8141261: Clean up building of demos Reviewed-by: erikj, tbell --- jdk/make/CompileDemos.gmk | 695 +++++++++++++++++++++----------------- 1 file changed, 379 insertions(+), 316 deletions(-) diff --git a/jdk/make/CompileDemos.gmk b/jdk/make/CompileDemos.gmk index 03b84fb725d..258b3425707 100644 --- a/jdk/make/CompileDemos.gmk +++ b/jdk/make/CompileDemos.gmk @@ -23,6 +23,10 @@ # questions. # +################################################################################ +# Build demos for the JDK into $(SUPPORT_OUTPUTDIR)/demos/image. +################################################################################ + default: all include $(SPEC) @@ -31,428 +35,487 @@ include JavaCompilation.gmk include NativeCompilation.gmk include SetupJavaCompilers.gmk include TextFileProcessing.gmk +include ZipArchive.gmk # Prepare the find cache. $(eval $(call FillCacheFind, $(JDK_TOPDIR)/src)) # Append demo goals to this variable. -BUILD_DEMOS = +TARGETS = # The demo structure and contents should really be cleaned up. # Now every other demo has its own quirks where to put the # READMEs and other files. DEMO_SHARE_SRC := $(JDK_TOPDIR)/src/demo/share -DEMO_CLOSED_SHARE_SRC := $(JDK_TOPDIR)/src/closed/demo/share -DEMO_SOLARIS_SRC := $(JDK_TOPDIR)/src/demo/solaris -DEMO_OS_TYPE_SRC := $(JDK_TOPDIR)/src/demo/$(OPENJDK_TARGET_OS_TYPE) GLOBAL_VERSION_INFO_RESOURCE := $(JDK_TOPDIR)/src/java.base/windows/native/common/version.rc -################################################################################################## +DEMO_MANIFEST := $(SUPPORT_OUTPUTDIR)/demos/java-main-manifest.mf -# This rule will be depended on due to the MANIFEST line +# This rule will be depended on due to the MANIFEST line in SetupBuildDemo +# and SetupBuildJvmtiDemo. $(eval $(call SetupTextFileProcessing, BUILD_JAVA_MANIFEST, \ SOURCE_FILES := $(JDK_TOPDIR)/make/data/mainmanifest/manifest.mf, \ - OUTPUT_FILE := $(SUPPORT_OUTPUTDIR)/demo/java-main-manifest.mf, \ + OUTPUT_FILE := $(DEMO_MANIFEST), \ REPLACEMENTS := \ @@RELEASE@@ => $(RELEASE) ; \ @@COMPANY_NAME@@ => $(COMPANY_NAME) , \ )) -define SetupAppletDemo - $$(eval $$(call SetupJavaCompilation,BUILD_DEMO_APPLET_$1, \ +################################################################################ +# Build applet demos. + +# Setup make rules for building a demo applet. +# +# Parameter 1 is the name of the rule. This name is used as variable prefix, +# and the targets generated are listed in a variable by that name. It is also +# used to locate the name of the applet subdir, and to determine the name +# of the output directory. +# +# Remaining parameters are named arguments. These include: +# SRC_DIR Alternative source directory to use for the demos. +# DISABLE_SJAVAC Passed to SetupJavaCompilation + +SetupBuildAppletDemo = $(NamedParamsMacroTemplate) +define SetupBuildAppletDemoBody + ifeq ($$($1_SRC_DIR), ) + $1_SRC_DIR := $(DEMO_SHARE_SRC)/applets + endif + + $$(eval $$(call SetupJavaCompilation, BUILD_DEMO_APPLET_$1, \ SETUP := GENERATE_USINGJDKBYTECODE, \ - SRC := $(JDK_TOPDIR)/src/$3demo/share/applets/$1, \ - BIN := $(SUPPORT_OUTPUTDIR)/demo/image/applets/$1, \ + SRC := $$($1_SRC_DIR)/$1, \ + BIN := $(SUPPORT_OUTPUTDIR)/demos/image/applets/$1, \ COPY := .html .java .xyz .obj .au .gif, \ - DISABLE_SJAVAC := $2)) - BUILD_DEMOS += $$(BUILD_DEMO_APPLET_$1) + DISABLE_SJAVAC := $$($1_DISABLE_SJAVAC), \ + )) + + $1 := $$(BUILD_DEMO_APPLET_$1) + + TARGETS += $$($1) endef ifneq ($(OPENJDK_TARGET_OS), solaris) - $(eval $(call SetupAppletDemo,ArcTest)) - $(eval $(call SetupAppletDemo,BarChart)) - $(eval $(call SetupAppletDemo,Blink)) - $(eval $(call SetupAppletDemo,CardTest)) - $(eval $(call SetupAppletDemo,Clock)) - $(eval $(call SetupAppletDemo,DitherTest)) - $(eval $(call SetupAppletDemo,DrawTest)) - $(eval $(call SetupAppletDemo,Fractal)) - $(eval $(call SetupAppletDemo,GraphicsTest)) - $(eval $(call SetupAppletDemo,NervousText)) - $(eval $(call SetupAppletDemo,SimpleGraph)) - $(eval $(call SetupAppletDemo,SortDemo)) - $(eval $(call SetupAppletDemo,SpreadSheet)) - - ifndef OPENJDK - $(eval $(call SetupAppletDemo,Animator,,closed/)) - $(eval $(call SetupAppletDemo,GraphLayout,true,closed/)) - $(eval $(call SetupAppletDemo,JumpingBox,,closed/)) - $(eval $(call SetupAppletDemo,TicTacToe,,closed/)) - endif + $(eval $(call SetupBuildAppletDemo, ArcTest)) + $(eval $(call SetupBuildAppletDemo, BarChart)) + $(eval $(call SetupBuildAppletDemo, Blink)) + $(eval $(call SetupBuildAppletDemo, CardTest)) + $(eval $(call SetupBuildAppletDemo, Clock)) + $(eval $(call SetupBuildAppletDemo, DitherTest)) + $(eval $(call SetupBuildAppletDemo, DrawTest)) + $(eval $(call SetupBuildAppletDemo, Fractal)) + $(eval $(call SetupBuildAppletDemo, GraphicsTest)) + $(eval $(call SetupBuildAppletDemo, NervousText)) + $(eval $(call SetupBuildAppletDemo, SimpleGraph)) + $(eval $(call SetupBuildAppletDemo, SortDemo)) + $(eval $(call SetupBuildAppletDemo, SpreadSheet)) endif -################################################################################################## +################################################################################ +# Build normal demos. -PATTERNS_TO_COPY = .html .txt .properties .js .gif .jpg .theme .data .opt README .c .h .png .ttf .xyz .obj +COPY_TO_JAR := .html .txt .properties .js .gif .jpg .theme .data .opt .c .h \ + .png .ttf .xyz .obj README COPYRIGHT -define SetupDemo - # Param 1 = Name of the demo - # Param 2 = Subdirectory of the demo below the demo directory. - # Param 3 = Additional javac flags. - # Param 4 = The main class for the jar. - # Param 5 = Additional source directory. - # Param 6 = Extra dir below $(JDK_TOPDIR)/src (closed) - # Param 7 = List of files to copy - # Param 8 = Base name of jar file. Defaults to $1 - # Param 9 = Exclude list - # Param 10 = Extra copy patterns - # Param 11 = Extra manifest attribute - # Param 12 = Suffix for compiler setup name +COPY_TO_IMAGE := *.html *.txt *.png *.xml README* - $1_SRC_BASE := $(JDK_TOPDIR)/src/$6demo/share/$2/$1 - # In some demos the source is found in a subdir called src. - $1_MAIN_SRC := $$(wildcard $$($1_SRC_BASE)/src) - ifeq ($$($1_MAIN_SRC), ) +# Setup make rules for building a demo. +# +# Parameter 1 is the name of the rule. This name is used as variable prefix, +# and the targets generated are listed in a variable by that name. +# +# Remaining parameters are named arguments. These include: +# DEMO_SUBDIR The name of the subdir of the demo, below the demo top dir. +# EXTRA_SRC_DIR Additional source directory. +# SRC_SUB_DIR Optional subdir to locate source code in +# SRC_DIR Alternative source directory to use for the demos. +# EXCLUDE_FILES Exclude file list +# JAR_NAME Base name of jar file. Defaults to $1. +# MAIN_CLASS The main class for the jar. Defaults to $1. +# EXTRA_COPY_TO_JAR Additional files to copy to jar (as patterns) +# EXTRA_COPY_TO_IMAGE Additional files to copy to images (as wildcards) +# EXTRA_MANIFEST_ATTR Extra manifest attribute +# SKIP_COMPILATION Skip Java compilation iff true +# DISABLE_SJAVAC Passed to SetupJavaCompilation +SetupBuildDemo = $(NamedParamsMacroTemplate) +define SetupBuildDemoBody + ifeq ($$($1_SRC_DIR), ) + $1_SRC_DIR := $(DEMO_SHARE_SRC) + endif + + $1_SRC_BASE := $$($1_SRC_DIR)/$$($1_DEMO_SUBDIR)/$1 + + # In some demos the source is found in a subdir + ifneq ($$($1_SRC_SUB_DIR), ) + $1_MAIN_SRC := $$($1_SRC_BASE)/$$($1_SRC_SUB_DIR) + else + # for allmost all $1_MAIN_SRC := $$($1_SRC_BASE) endif - ifneq ($8, ) - $1_JARFILE := $8.jar - else - $1_JARFILE := $1.jar + # Default is to use demo name as jar file name. + ifeq ($$($1_JAR_NAME), ) + $1_JAR_NAME := $1 endif - ifeq ($(findstring $1,Laffy SwingSet3), ) - $$(eval $$(call SetupJavaCompilation,BUILD_DEMO_$1, \ + # Default is to use demo name as jar main class. + ifeq ($$($1_MAIN_CLASS), ) + $1_MAIN_CLASS := $1 + else ifeq ($$($1_MAIN_CLASS), NONE) + $1_MAIN_CLASS := + $1_EXTRA_MANIFEST_ATTR += Main-Class: \n + endif + + ifneq ($$($1_SKIP_COMPILATION), true) + $$(eval $$(call SetupJavaCompilation, BUILD_DEMO_$1, \ SETUP := GENERATE_USINGJDKBYTECODE, \ - ADD_JAVAC_FLAGS := $3, \ - SRC := $$($1_MAIN_SRC) $5, \ - BIN := $(SUPPORT_OUTPUTDIR)/demo/classes/$2/$1, \ - COPY := $(PATTERNS_TO_COPY) $(10), \ - JAR := $(SUPPORT_OUTPUTDIR)/demo/image/$2/$1/$$($1_JARFILE), \ - JARMAIN := $4, \ - MANIFEST := $(SUPPORT_OUTPUTDIR)/demo/java-main-manifest.mf, \ - EXTRA_MANIFEST_ATTR := $(11), \ - SRCZIP := $(SUPPORT_OUTPUTDIR)/demo/image/$2/$1/src.zip, \ - EXCLUDE_FILES := $9, \ - DISABLE_SJAVAC := $(12))) + SRC := $$($1_MAIN_SRC) $$($1_EXTRA_SRC_DIR), \ + BIN := $(SUPPORT_OUTPUTDIR)/demos/classes/$$($1_DEMO_SUBDIR)/$1, \ + COPY := $(COPY_TO_JAR) $$($1_EXTRA_COPY_TO_JAR), \ + JAR := $(SUPPORT_OUTPUTDIR)/demos/image/$$($1_DEMO_SUBDIR)/$1/$$($1_JAR_NAME).jar, \ + JARMAIN := $$($1_MAIN_CLASS), \ + MANIFEST := $(DEMO_MANIFEST), \ + EXTRA_MANIFEST_ATTR := $$($1_EXTRA_MANIFEST_ATTR), \ + SRCZIP := $(SUPPORT_OUTPUTDIR)/demos/image/$$($1_DEMO_SUBDIR)/$1/src.zip, \ + EXCLUDE_FILES := $$($1_EXCLUDE_FILES), \ + DISABLE_SJAVAC := $$($1_DISABLE_SJAVAC), \ + )) - BUILD_DEMOS += $$(BUILD_DEMO_$1) \ - $(SUPPORT_OUTPUTDIR)/demo/image/$2/$1/$$($1_JARFILE) \ - $(SUPPORT_OUTPUTDIR)/demo/image/$2/$1/src.zip + $1 += $$(BUILD_DEMO_$1) endif - # Copy files. - $1_COPY_TARGETS := $$(patsubst $$($1_SRC_BASE)/%, \ - $(SUPPORT_OUTPUTDIR)/demo/image/$2/$1/%, \ - $$(wildcard $$(addprefix $$($1_SRC_BASE)/, $7))) - ifneq ($7, ) - $(SUPPORT_OUTPUTDIR)/demo/image/$2/$1/%: $$($1_SRC_BASE)/% - $$(call install-file) - $(CHMOD) -f ug+w $$@ + # Copy files. Sort is needed to remove duplicates. + $1_COPY_FILES := $$(sort $$(wildcard $$(addprefix $$($1_SRC_BASE)/, \ + $(COPY_TO_IMAGE) $$($1_EXTRA_COPY_TO_IMAGE)))) + $$(eval $$(call SetupCopyFiles, COPY_DEMO_$1, \ + SRC := $$($1_SRC_BASE), \ + DEST := $(SUPPORT_OUTPUTDIR)/demos/image/$$($1_DEMO_SUBDIR)/$1, \ + FILES := $$($1_COPY_FILES), \ + )) - BUILD_DEMOS += $$($1_COPY_TARGETS) - endif + $1 += $$(COPY_DEMO_$1) + TARGETS += $$($1) endef -$(eval $(call SetupDemo,CodePointIM,jfc,,CodePointIM,,,*.html)) -$(SUPPORT_OUTPUTDIR)/demo/image/jfc/CodePointIM/_the.services: \ - $(SUPPORT_OUTPUTDIR)/demo/image/jfc/CodePointIM/CodePointIM.jar \ - $(DEMO_SHARE_SRC)/jfc/CodePointIM/java.awt.im.spi.InputMethodDescriptor - (cd $(SUPPORT_OUTPUTDIR)/demo/image/jfc/CodePointIM && \ - $(MKDIR) -p _the.tmp/META-INF/services && \ - $(CP) $(DEMO_SHARE_SRC)/jfc/CodePointIM/java.awt.im.spi.InputMethodDescriptor _the.tmp/META-INF/services && \ - cd ./_the.tmp && \ - $(JAR) uf $(SUPPORT_OUTPUTDIR)/demo/image/jfc/CodePointIM/CodePointIM.jar META-INF/services/java.awt.im.spi.InputMethodDescriptor && \ - cd ./META-INF/services && \ - $(JAR) uf $(SUPPORT_OUTPUTDIR)/demo/image/jfc/CodePointIM/CodePointIM.jar java.awt.im.spi.InputMethodDescriptor) - $(RM) -r $(SUPPORT_OUTPUTDIR)/demo/image/jfc/CodePointIM/_the.tmp - $(TOUCH) $@ +CODEPOINT_SERVICE := java.awt.im.spi.InputMethodDescriptor +CODEPOINT_METAINF_SERVICE_FILE := \ + $(SUPPORT_OUTPUTDIR)/demos/classes/jfc/CodePointIM/META-INF/services/$(CODEPOINT_SERVICE) -BUILD_DEMOS += $(SUPPORT_OUTPUTDIR)/demo/image/jfc/CodePointIM/_the.services +$(eval $(call SetupBuildDemo, CodePointIM, \ + DEMO_SUBDIR := jfc, \ + EXTRA_COPY_TO_JAR := $(CODEPOINT_SERVICE), \ +)) + +# We also need to copy the CODEPOINT_SERVICE file to the META-INF/services +# location, and make sure the jar depends on that file to get it included. +$(CODEPOINT_METAINF_SERVICE_FILE): $(DEMO_SHARE_SRC)/jfc/CodePointIM/$(CODEPOINT_SERVICE) + $(call install-file) + +$(BUILD_DEMO_CodePointIM_JAR): $(CODEPOINT_METAINF_SERVICE_FILE) ifneq ($(OPENJDK_TARGET_OS), solaris) - $(eval $(call SetupDemo,MoleculeViewer,applets,,XYZChemModel,,,example*.html *.java)) - $(eval $(call SetupDemo,WireFrame,applets,,ThreeD,,,example*.html *.java)) - $(eval $(call SetupDemo,SwingApplet,jfc,,SwingApplet,,,README* *.html)) -endif -$(eval $(call SetupDemo,FileChooserDemo,jfc,,FileChooserDemo,,,README*)) -$(eval $(call SetupDemo,Font2DTest,jfc,,Font2DTest,,,*.html *.txt)) -$(eval $(call SetupDemo,Metalworks,jfc,,Metalworks,,,README*)) -$(eval $(call SetupDemo,Notepad,jfc,,Notepad,,,README*)) -$(eval $(call SetupDemo,SampleTree,jfc,,SampleTree,,,README*)) -$(eval $(call SetupDemo,TableExample,jfc,,TableExample,,,README*)) -$(eval $(call SetupDemo,TransparentRuler,jfc,,transparentruler.Ruler,,,README*)) -$(eval $(call SetupDemo,jconsole-plugin,scripting,,,,,*.xml *.txt,,,,Main-Class: \n)) -$(eval $(call SetupDemo,FullThreadDump,management,,FullThreadDump,,,README*)) -$(eval $(call SetupDemo,JTop,management,,JTop,,,README*)) -$(eval $(call SetupDemo,MemoryMonitor,management,,MemoryMonitor,,,README*)) -$(eval $(call SetupDemo,VerboseGC,management,,VerboseGC,,,README*)) + $(eval $(call SetupBuildDemo, MoleculeViewer, \ + DEMO_SUBDIR := applets, \ + MAIN_CLASS := XYZChemModel, \ + EXTRA_COPY_TO_IMAGE := *.java, \ + )) -ifndef OPENJDK - $(eval $(call SetupDemo,Laffy,jfc,,,,closed/,*)) - $(eval $(call SetupDemo,SwingSet3,jfc,,,,closed/,*)) + $(eval $(call SetupBuildDemo, WireFrame, \ + DEMO_SUBDIR := applets, \ + MAIN_CLASS := ThreeD, \ + EXTRA_COPY_TO_IMAGE := *.java, \ + )) - $(eval $(call SetupDemo,Java2D,jfc,,java2d.Java2Demo,,closed/,*.html README*,Java2Demo)) - $(eval $(call SetupDemo,Stylepad,jfc,,Stylepad, \ - $(DEMO_SHARE_SRC)/jfc/Notepad,closed/,*.txt,,$(DEMO_SHARE_SRC)/jfc/Notepad/README.txt)) - $(eval $(call SetupDemo,SwingSet2,jfc,,SwingSet2,,closed/,README* *.html,,,.java COPYRIGHT, \ - SplashScreen-Image: resources/images/splash.png,true)) - - BUILD_DEMOS += $(patsubst $(DEMO_CLOSED_SHARE_SRC)/nbproject/%, \ - $(SUPPORT_OUTPUTDIR)/demo/image/nbproject/%, \ - $(call CacheFind, $(DEMO_CLOSED_SHARE_SRC)/nbproject)) - - $(SUPPORT_OUTPUTDIR)/demo/image/nbproject/%: $(DEMO_CLOSED_SHARE_SRC)/nbproject/% - $(call install-file) - $(CHMOD) -f ug+w $@ + $(eval $(call SetupBuildDemo, SwingApplet, \ + DEMO_SUBDIR := jfc, \ + )) endif -################################################################################################## +$(eval $(call SetupBuildDemo, FileChooserDemo, \ + DEMO_SUBDIR := jfc, \ +)) -# In the old makefiles, j2dbench was not compiled. -#$(eval $(call SetupDemo,J2DBench, java2d, /src, , j2dbench/J2DBench)) +$(eval $(call SetupBuildDemo, Font2DTest, \ + DEMO_SUBDIR := jfc, \ +)) -# JVMTI demos are a bit strange and share some files, but be careful the -# shared files are just the *.c and *.h files, not the README or sample -# makefiles. So we always exclude the README.txt and sample.makefile.txt -# from the extra sources. -define SetupJVMTIDemo - # Param 1 = Name of the demo - # Param 2 = add these directories to the includes, default is agent_util - # Param 3 = extra CFLAGS - # Param 4 = C or C++ (defaults to C) - # Param 5 = libs for unix - # Param 6 = libs for windows - # Param 7 = libs for solaris - # Param 8 = libs for linux - # Param 9 = extra directories with required sources - # Param 10 = DISABLED_WARNINGS_gcc - # Param 11 = DISABLED_WARNINGS_microsoft - # Param 12 = DISABLED_WARNINGS_clang - BUILD_DEMO_JVMTI_$1_EXTRA_SRC := \ - $$(wildcard $(DEMO_OS_TYPE_SRC)/jvmti/$1) \ - $$(wildcard $$(addprefix $(DEMO_SHARE_SRC)/jvmti/, $2)) \ - $9 - BUILD_DEMO_JVMTI_$1_EXTRA_SRC_EXCLUDE := \ - $$(wildcard $$(patsubst %, $(DEMO_SHARE_SRC)/jvmti/%/README.txt, $2)) \ - $$(wildcard $$(patsubst %, $(DEMO_SHARE_SRC)/jvmti/%/sample.makefile.txt, $2)) - BUILD_DEMO_JVMTI_$1_EXTRA_INC := $$(addprefix -I, $$(BUILD_DEMO_JVMTI_$1_EXTRA_SRC)) - ifeq (C++, $4) - BUILD_DEMO_JVMTI_$1_TOOLCHAIN := TOOLCHAIN_LINK_CXX - $1_EXTRA_CXX := $(LDFLAGS_CXX_JDK) $(LIBCXX) +$(eval $(call SetupBuildDemo, Metalworks, \ + DEMO_SUBDIR := jfc, \ +)) + +$(eval $(call SetupBuildDemo, Notepad, \ + DEMO_SUBDIR := jfc, \ +)) + +$(eval $(call SetupBuildDemo, SampleTree, \ + DEMO_SUBDIR := jfc, \ +)) + +$(eval $(call SetupBuildDemo, TableExample, \ + DEMO_SUBDIR := jfc, \ +)) + +$(eval $(call SetupBuildDemo, TransparentRuler, \ + DEMO_SUBDIR := jfc, \ + MAIN_CLASS := transparentruler.Ruler, \ +)) + +$(eval $(call SetupBuildDemo, jconsole-plugin, \ + DEMO_SUBDIR := scripting, \ + SRC_SUB_DIR := src, \ + MAIN_CLASS := NONE, \ +)) + +$(eval $(call SetupBuildDemo, FullThreadDump, \ + DEMO_SUBDIR := management, \ +)) + +$(eval $(call SetupBuildDemo, JTop, \ + DEMO_SUBDIR := management, \ +)) + +$(eval $(call SetupBuildDemo, MemoryMonitor, \ + DEMO_SUBDIR := management, \ +)) + +$(eval $(call SetupBuildDemo, VerboseGC, \ + DEMO_SUBDIR := management, \ +)) + +################################################################################ +# Build JVMTI demos. + +# Setup make rules for building a JVMTI demo. +# +# Parameter 1 is the name of the rule. This name is used as variable prefix, +# and the targets generated are listed in a variable by that name. +# +# Remaining parameters are named arguments. These include: +# EXTRA_SRC_SUBDIR Also include these subdirectories +# TOOLCHAIN Optionally specify toolchain to use +SetupBuildJvmtiDemo = $(NamedParamsMacroTemplate) +define SetupBuildJvmtiDemoBody + $1_SRC := \ + $(DEMO_SHARE_SRC)/jvmti/$1 \ + $$(wildcard $$(addprefix $(DEMO_SHARE_SRC)/jvmti/, \ + agent_util $$($1_EXTRA_SRC_SUBDIR))) + + ### Build the native lib + $1_CFLAGS_INCLUDE := $$(addprefix -I, $$($1_SRC)) + + $1_CXXFLAGS := $$($1_CFLAGS_INCLUDE) $(CXXFLAGS_JDKLIB) $(CXXFLAGS_DEBUG_SYMBOLS) + + ifeq ($$($1_TOOLCHAIN), TOOLCHAIN_LINK_CXX) + # For C++, we also need some special treatment. + $1_LDFLAGS := $(LDFLAGS_CXX_JDK) + $1_LIBS := $(LIBCXX) + + ifeq ($(OPENJDK_TARGET_CPU_ARCH), sparc) + $1_CXXFLAGS := $$(filter-out -xregs=no%appl, $$($1_CXXFLAGS)) + endif endif - $1_CXXFLAGS := $(CXXFLAGS_JDKLIB) -I$(DEMO_SHARE_SRC)/jvmti/$1 \ - $$(BUILD_DEMO_JVMTI_$1_EXTRA_INC) $3 \ - $(CXXFLAGS_DEBUG_SYMBOLS) - ifeq ($1-$(OPENJDK_TARGET_CPU_ARCH), waiters-sparc) - $1_FILTER := -xregs=no%appl - $1_CXXFLAGS := $$(filter-out $$($1_FILTER), $$($1_CXXFLAGS)) - endif - - # Workaround for CFLAGS_JDKLIB containing ',' on solaris. If this is added as 'CFLAGS' to the - # eval call below, the comma gets expanded too early. - BUILD_DEMO_JVMTI_$1_CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_DEBUG_SYMBOLS) \ - -I$(DEMO_SHARE_SRC)/jvmti/$1 $$(BUILD_DEMO_JVMTI_$1_EXTRA_INC) $3 - # Remove the -incremental:no setting to get .ilk-files like in the old build. - $$(eval $$(call SetupNativeCompilation,BUILD_DEMO_JVMTI_$1, \ - SRC := $(DEMO_SHARE_SRC)/jvmti/$1 $$(BUILD_DEMO_JVMTI_$1_EXTRA_SRC), \ - TOOLCHAIN := $$(BUILD_DEMO_JVMTI_$1_TOOLCHAIN), \ + $$(eval $$(call SetupNativeCompilation, BUILD_DEMO_JVMTI_NATIVE_$1, \ + SRC := $$($1_SRC), \ + TOOLCHAIN := $$($1_TOOLCHAIN), \ OPTIMIZATION := LOW, \ + CFLAGS := $$($1_CFLAGS_INCLUDE) $$(CFLAGS_JDKLIB) $$(CFLAGS_DEBUG_SYMBOLS), \ CXXFLAGS := $$($1_CXXFLAGS), \ - DISABLED_WARNINGS_gcc := $(10), \ - DISABLED_WARNINGS_clang := $(12), \ - DISABLED_WARNINGS_microsoft := $(11), \ - LDFLAGS := $(filter-out -incremental:no -opt:ref, $(LDFLAGS_JDKLIB)), \ + LDFLAGS := $(filter-out -incremental:no -opt:ref, $(LDFLAGS_JDKLIB)) \ + $$($1_LDFLAGS), \ LDFLAGS_macosx := $(call SET_EXECUTABLE_ORIGIN), \ - LIBS := $$($1_EXTRA_CXX), \ - LIBS_unix := $5, \ - LIBS_linux := $8, \ - LIBS_solaris := $7 -lc, \ - LIBS_windows := $6, \ + LIBS := $$($1_LIBS), \ + LIBS_solaris := -lc, \ VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \ RC_FLAGS := $$(RC_FLAGS) \ -D "JDK_FNAME=$1.dll" \ -D "JDK_INTERNAL_NAME=$1" \ -D "JDK_FTYPE=0x2L", \ - OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/demo/native/jvmti/$1, \ - OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/lib, \ - LIBRARY := $1)) + OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/demos/native/jvmti/$1, \ + OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/demos/image/jvmti/$1/lib, \ + LIBRARY := $1, \ + )) - $$(eval $$(call SetupZipArchive,BUILD_DEMO_JVMTI_SRC_$1, \ - SRC := $(DEMO_SHARE_SRC)/jvmti/$1 $$(BUILD_DEMO_JVMTI_$1_EXTRA_SRC), \ - EXCLUDE_FILES := $$(BUILD_DEMO_JVMTI_$1_EXTRA_SRC_EXCLUDE), \ - ZIP := $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/src.zip)) + $1 += $$(BUILD_DEMO_JVMTI_NATIVE_$1) - $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/README.txt: $(DEMO_SHARE_SRC)/jvmti/$1/README.txt + ### Build the jar, if we have java sources + ifneq ($$(wildcard $(DEMO_SHARE_SRC)/jvmti/$1/*.java), ) + $$(eval $$(call SetupJavaCompilation, BUILD_DEMO_JVMTI_JAVA_$1, \ + SETUP := GENERATE_USINGJDKBYTECODE, \ + SRC := $(DEMO_SHARE_SRC)/jvmti/$1, \ + BIN := $(SUPPORT_OUTPUTDIR)/demos/classes/jvmti/$1, \ + COPY := $(COPY_TO_JAR), \ + JAR := $(SUPPORT_OUTPUTDIR)/demos/image/jvmti/$1/$1.jar, \ + EXTRA_MANIFEST_ATTR := Main-Class: \n, \ + MANIFEST := $(DEMO_MANIFEST), \ + )) + + $1 += $$(BUILD_DEMO_JVMTI_JAVA_$1_JAR) + endif + + ### Build the source zip + $1_EXCLUDE_FILES := \ + $$(wildcard $$(patsubst %, $(DEMO_SHARE_SRC)/jvmti/%/README.txt, \ + agent_util $$($1_EXTRA_SRC_SUBDIR))) \ + $$(wildcard $$(patsubst %, $(DEMO_SHARE_SRC)/jvmti/%/sample.makefile.txt, \ + agent_util $$($1_EXTRA_SRC_SUBDIR))) + + $$(eval $$(call SetupZipArchive, BUILD_DEMO_JVMTI_SRC_$1, \ + SRC := $$($1_SRC), \ + EXCLUDE_FILES := $$($1_EXCLUDE_FILES), \ + ZIP := $(SUPPORT_OUTPUTDIR)/demos/image/jvmti/$1/src.zip, \ + )) + + $1 += $$(BUILD_DEMO_JVMTI_SRC_$1) + + # Copy files to image + $(SUPPORT_OUTPUTDIR)/demos/image/jvmti/$1/README.txt: $(DEMO_SHARE_SRC)/jvmti/$1/README.txt $$(call install-file) $(CHMOD) -f ug+w $$@ - ifneq (, $$(wildcard $(DEMO_SHARE_SRC)/jvmti/$1/*.java)) - $$(eval $$(call SetupJavaCompilation,BUILD_DEMO_JVMTI_$1_JAVA, \ - SETUP := GENERATE_USINGJDKBYTECODE, \ - SRC := $(DEMO_SHARE_SRC)/jvmti/$1, \ - BIN := $(SUPPORT_OUTPUTDIR)/demo/classes/jvmti/$1, \ - COPY := $(PATTERNS_TO_COPY), \ - JAR := $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/$1.jar, \ - EXTRA_MANIFEST_ATTR := Main-Class: \n, \ - MANIFEST := $(SUPPORT_OUTPUTDIR)/demo/java-main-manifest.mf)) - - BUILD_DEMOS += $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/$1.jar - endif - - BUILD_DEMOS += $$(BUILD_DEMO_JVMTI_$1) \ - $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/src.zip \ - $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/README.txt + $1 += $(SUPPORT_OUTPUTDIR)/demos/image/jvmti/$1/README.txt ifeq ($(OPENJDK_TARGET_OS), windows) - # These files normally end up in OBJECT_DIR but for demos they - # are supposed to be included in the distro. - $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/lib/$1.lib: $$(BUILD_DEMO_JVMTI_$1) - $(CP) $(SUPPORT_OUTPUTDIR)/demo/native/jvmti/$1/$1.lib $$@ + # These lib and exp files normally end up in OBJECT_DIR but for demos they + # are supposed to be included in the distro. Since they are created as + # a side-effect of the library compilation, make does not know about them. + $1_SUPPORT_OUTPUTDIR := $(SUPPORT_OUTPUTDIR)/demos/native/jvmti/$1 + $1_IMAGE_OUTPUTDIR := $(SUPPORT_OUTPUTDIR)/demos/image/jvmti/$1/lib - $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/lib/$1.exp: $$(BUILD_DEMO_JVMTI_$1) - $(CP) $(SUPPORT_OUTPUTDIR)/demo/native/jvmti/$1/$1.exp $$@ + $$($1_SUPPORT_OUTPUTDIR)/$1.lib: $$(BUILD_DEMO_JVMTI_NATIVE_$1) - BUILD_DEMOS += $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/lib/$1.lib \ - $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/$1/lib/$1.exp + $$($1_SUPPORT_OUTPUTDIR)/$1.exp: $$(BUILD_DEMO_JVMTI_NATIVE_$1) + + $$($1_IMAGE_OUTPUTDIR)/$1.lib: $$($1_SUPPORT_OUTPUTDIR)/$1.lib + $$(call install-file) + + $$($1_IMAGE_OUTPUTDIR)/$1.exp: $$($1_SUPPORT_OUTPUTDIR)/$1.exp + $$(call install-file) + + $1 += $$($1_IMAGE_OUTPUTDIR)/$1.lib $$($1_IMAGE_OUTPUTDIR)/$1.exp endif + + TARGETS += $$($1) endef -$(eval $(call SetupJVMTIDemo,compiledMethodLoad, agent_util)) -$(eval $(call SetupJVMTIDemo,gctest, agent_util)) -$(eval $(call SetupJVMTIDemo,heapTracker, agent_util java_crw_demo)) -$(eval $(call SetupJVMTIDemo,heapViewer, agent_util)) -$(eval $(call SetupJVMTIDemo,minst, agent_util java_crw_demo)) -$(eval $(call SetupJVMTIDemo,mtrace, agent_util java_crw_demo)) -$(eval $(call SetupJVMTIDemo,waiters, agent_util, , C++)) -$(eval $(call SetupJVMTIDemo,versionCheck, agent_util)) +$(eval $(call SetupBuildJvmtiDemo, compiledMethodLoad)) +$(eval $(call SetupBuildJvmtiDemo, gctest)) +$(eval $(call SetupBuildJvmtiDemo, heapViewer)) +$(eval $(call SetupBuildJvmtiDemo, versionCheck)) -################################################################################################## +$(eval $(call SetupBuildJvmtiDemo, heapTracker, \ + EXTRA_SRC_SUBDIR := java_crw_demo, \ +)) -$(SUPPORT_OUTPUTDIR)/demo/image/management/index.html: $(DEMO_SHARE_SRC)/management/index.html - $(call install-file) - $(CHMOD) -f ug+w $@ +$(eval $(call SetupBuildJvmtiDemo, minst, \ + EXTRA_SRC_SUBDIR := java_crw_demo, \ +)) -$(SUPPORT_OUTPUTDIR)/demo/image/jvmti/index.html: $(DEMO_SHARE_SRC)/jvmti/index.html - $(call install-file) - $(CHMOD) -f ug+w $@ +$(eval $(call SetupBuildJvmtiDemo, mtrace, \ + EXTRA_SRC_SUBDIR := java_crw_demo, \ +)) -BUILD_DEMOS += $(SUPPORT_OUTPUTDIR)/demo/image/management/index.html \ - $(SUPPORT_OUTPUTDIR)/demo/image/jvmti/index.html +$(eval $(call SetupBuildJvmtiDemo, waiters, \ + TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ +)) -################################################################################################## - -# The netbeans project files are copied into the demo directory. -ifeq ($(OPENJDK_TARGET_OS), solaris) - BUILD_DEMOS += $(patsubst $(DEMO_SHARE_SRC)/nbproject/%, \ - $(SUPPORT_OUTPUTDIR)/demo/image/nbproject/%, \ - $(filter-out $(DEMO_SHARE_SRC)/nbproject/jfc/SwingApplet%, \ - $(call CacheFind, $(DEMO_SHARE_SRC)/nbproject))) -else - BUILD_DEMOS += $(patsubst $(DEMO_SHARE_SRC)/nbproject/%, \ - $(SUPPORT_OUTPUTDIR)/demo/image/nbproject/%, \ - $(call CacheFind, $(DEMO_SHARE_SRC)/nbproject)) -endif - -$(SUPPORT_OUTPUTDIR)/demo/image/nbproject/%: $(DEMO_SHARE_SRC)/nbproject/% - $(call install-file) - $(CHMOD) -f ug+w $@ - -################################################################################################## - -$(SUPPORT_OUTPUTDIR)/demo/image/README: $(DEMO_SHARE_SRC)/README - $(call install-file) - -BUILD_DEMOS += $(SUPPORT_OUTPUTDIR)/demo/image/README - -################################################################################################## +################################################################################ +# Build the Poller demo (on Solaris only). ifeq ($(OPENJDK_TARGET_OS), solaris) + DEMO_SOLARIS_SRC := $(JDK_TOPDIR)/src/demo/solaris - $(SUPPORT_OUTPUTDIR)/demo/classes/jni/Poller/%: $(DEMO_SOLARIS_SRC)/jni/Poller/% - $(call install-file) - $(CHMOD) -f ug+w $@ - - $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/README.txt: $(DEMO_SOLARIS_SRC)/jni/Poller/README.txt - $(call install-file) - $(CHMOD) -f ug+w $@ - - $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/Poller.jar: \ - $(SUPPORT_OUTPUTDIR)/demo/classes/jni/Poller/README.txt \ - $(SUPPORT_OUTPUTDIR)/demo/classes/jni/Poller/Poller.c - - $(eval $(call SetupJavaCompilation,BUILD_DEMO_POLLER_JAR, \ + $(eval $(call SetupJavaCompilation, BUILD_DEMO_JAVA_Poller, \ SETUP := GENERATE_USINGJDKBYTECODE, \ SRC := $(DEMO_SOLARIS_SRC)/jni/Poller, \ - BIN := $(SUPPORT_OUTPUTDIR)/demo/classes/jni/Poller, \ - HEADERS := $(SUPPORT_OUTPUTDIR)/demo/classes/jni/Poller, \ - JAR := $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/Poller.jar, \ - MANIFEST := $(SUPPORT_OUTPUTDIR)/demo/java-main-manifest.mf, \ - SRCZIP := $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/src.zip, \ + BIN := $(SUPPORT_OUTPUTDIR)/demos/classes/jni/Poller, \ + HEADERS := $(SUPPORT_OUTPUTDIR)/demos/classes/jni/Poller, \ + JAR := $(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/Poller.jar, \ + MANIFEST := $(SUPPORT_OUTPUTDIR)/demos/java-main-manifest.mf, \ + SRCZIP := $(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/src.zip, \ COPY := README.txt Poller.c, \ - JARMAIN := Client)) + JARMAIN := Client, \ + )) + TARGETS += $(BUILD_DEMO_JAVA_Poller) - - BUILD_DEMOS += $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/Poller.jar \ - $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/src.zip \ - $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/README.txt - - $(eval $(call SetupNativeCompilation,BUILD_LIBPOLLER, \ + $(eval $(call SetupNativeCompilation, BUILD_DEMO_NATIVE_Poller, \ SRC := $(DEMO_SOLARIS_SRC)/jni/Poller, \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) \ - -I$(SUPPORT_OUTPUTDIR)/demo/classes/jni/Poller, \ + -I$(SUPPORT_OUTPUTDIR)/demos/classes/jni/Poller, \ LDFLAGS := $(LDFLAGS_JDKLIB), \ LIBS_solaris := -lc, \ - OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/demo/native/jni/Poller, \ - OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/demo/native, \ - LIBRARY := Poller)) + OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/demos/native/jni/Poller, \ + OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/demos/native, \ + LIBRARY := Poller, \ + )) - # - # We can only compile native code after jar has been build (since we depend on generated .h files) - # - $(SUPPORT_OUTPUTDIR)/demo/native/jni/Poller/Poller.o: $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/Poller.jar + TARGETS += $(BUILD_DEMO_NATIVE_Poller) - $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/lib/$(LIBRARY_PREFIX)Poller$(SHARED_LIBRARY_SUFFIX): \ - $(SUPPORT_OUTPUTDIR)/demo/native/$(LIBRARY_PREFIX)Poller$(SHARED_LIBRARY_SUFFIX) + # We can only compile native code after java has been compiled (since we + # depend on generated .h files) + $(SUPPORT_OUTPUTDIR)/demos/native/jni/Poller/Poller.o: \ + $(BUILD_DEMO_JAVA_POLLER_COMPILE_TARGETS) + + # Copy to image + $(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/README.txt: \ + $(DEMO_SOLARIS_SRC)/jni/Poller/README.txt + $(call install-file) + $(CHMOD) -f ug+w $@ + + TARGETS += $(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/README.txt + + $(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/lib/libPoller.so: \ + $(SUPPORT_OUTPUTDIR)/demos/native/libPoller.so $(call install-file) - BUILD_DEMOS += $(SUPPORT_OUTPUTDIR)/demo/image/jni/Poller/lib/$(LIBRARY_PREFIX)Poller$(SHARED_LIBRARY_SUFFIX) - + TARGETS += $(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/lib/libPoller.so endif -################################################################################################## +################################################################################ +# Copy html and README files. -ifndef OPENJDK - DB_ZIP_DIR := $(wildcard $(JDK_TOPDIR)/src/closed/db) - DB_DEMO_ZIPFILE := $(wildcard $(DB_ZIP_DIR)/*.zip) +$(SUPPORT_OUTPUTDIR)/demos/image/management/index.html: $(DEMO_SHARE_SRC)/management/index.html + $(call install-file) + $(CHMOD) -f ug+w $@ - $(SUPPORT_OUTPUTDIR)/demo/image/_the.db.unzipped: $(DB_DEMO_ZIPFILE) - $(MKDIR) -p $(@D) - $(RM) -r $(SUPPORT_OUTPUTDIR)/demo/image/db $(SUPPORT_OUTPUTDIR)/demo/image/demo - $(CD) $(SUPPORT_OUTPUTDIR)/demo/image && $(UNZIP) -q -o $< - $(MV) $(SUPPORT_OUTPUTDIR)/demo/image/db-derby-*-bin/demo $(SUPPORT_OUTPUTDIR)/demo/image/db - $(CD) $(SUPPORT_OUTPUTDIR)/demo/image && $(RM) -r db-derby-*-bin - $(TOUCH) $@ +$(SUPPORT_OUTPUTDIR)/demos/image/jvmti/index.html: $(DEMO_SHARE_SRC)/jvmti/index.html + $(call install-file) + $(CHMOD) -f ug+w $@ - # Copy this after the unzip above to avoid race with directory creation and mv command. - $(SUPPORT_OUTPUTDIR)/demo/image/db/README-JDK-DEMOS.html: \ - $(DB_ZIP_DIR)/README-JDK-DEMOS.html \ - | $(SUPPORT_OUTPUTDIR)/demo/image/_the.db.unzipped - $(MKDIR) -p $(@D) - $(CAT) $< | $(SED) "s/XXXX/$(shell cat $(DB_ZIP_DIR)/COPYRIGHTYEAR)/" > $@ +$(SUPPORT_OUTPUTDIR)/demos/image/README: $(DEMO_SHARE_SRC)/README + $(call install-file) - BUILD_DEMOS += $(SUPPORT_OUTPUTDIR)/demo/image/_the.db.unzipped $(SUPPORT_OUTPUTDIR)/demo/image/db/README-JDK-DEMOS.html +TARGETS += $(SUPPORT_OUTPUTDIR)/demos/image/management/index.html \ + $(SUPPORT_OUTPUTDIR)/demos/image/jvmti/index.html \ + $(SUPPORT_OUTPUTDIR)/demos/image/README + +################################################################################ +# Copy netbeans project files. + +$(SUPPORT_OUTPUTDIR)/demos/image/nbproject/%: $(DEMO_SHARE_SRC)/nbproject/% + $(call install-file) + $(CHMOD) -f ug+w $@ + +ifeq ($(OPENJDK_TARGET_OS), solaris) + TARGETS += $(patsubst $(DEMO_SHARE_SRC)/nbproject/%, \ + $(SUPPORT_OUTPUTDIR)/demos/image/nbproject/%, \ + $(filter-out $(DEMO_SHARE_SRC)/nbproject/jfc/SwingApplet%, \ + $(call CacheFind, $(DEMO_SHARE_SRC)/nbproject))) +else + TARGETS += $(patsubst $(DEMO_SHARE_SRC)/nbproject/%, \ + $(SUPPORT_OUTPUTDIR)/demos/image/nbproject/%, \ + $(call CacheFind, $(DEMO_SHARE_SRC)/nbproject)) endif -################################################################################################## +################################################################################ -all: $(BUILD_DEMOS) +# Hook to include the corresponding custom file, if present. +$(eval $(call IncludeCustomExtension, jdk, CompileDemos.gmk)) + +all: $(TARGETS) .PHONY: all From 61aa204f408415fd3b4c99fe16500ac84b557004 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Tue, 3 Nov 2015 17:54:25 +0100 Subject: [PATCH 20/31] 8141333: Rename SetupArchive to SetupJarArchive Reviewed-by: erikj, tbell --- jdk/make/gendata/GendataPolicyJars.gmk | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/jdk/make/gendata/GendataPolicyJars.gmk b/jdk/make/gendata/GendataPolicyJars.gmk index 256b32e2b58..82e2e424446 100644 --- a/jdk/make/gendata/GendataPolicyJars.gmk +++ b/jdk/make/gendata/GendataPolicyJars.gmk @@ -27,7 +27,7 @@ default: all include $(SPEC) include MakeBase.gmk -include JavaCompilation.gmk +include JarArchive.gmk ################################################################################ @@ -57,7 +57,7 @@ ifndef OPENJDK endif # -# TODO fix so that SetupArchive does not write files into SRCS +# TODO fix so that SetupJarArchive does not write files into SRCS # then we don't need this extra copying # # NOTE: We currently do not place restrictions on our limited export @@ -76,13 +76,14 @@ $(US_EXPORT_POLICY_JAR_TMP)/%: $(US_EXPORT_POLICY_JAR_SRC_DIR)/% US_EXPORT_POLICY_JAR_DEPS := \ $(US_EXPORT_POLICY_JAR_TMP)/default_US_export.policy -$(eval $(call SetupArchive,BUILD_US_EXPORT_POLICY_JAR, \ +$(eval $(call SetupJarArchive, BUILD_US_EXPORT_POLICY_JAR, \ DEPENDENCIES := $(US_EXPORT_POLICY_JAR_DEPS), \ SRCS := $(US_EXPORT_POLICY_JAR_TMP), \ SUFFIXES := .policy, \ JAR := $(US_EXPORT_POLICY_JAR_UNLIMITED), \ EXTRA_MANIFEST_ATTR := Crypto-Strength: unlimited, \ - SKIP_METAINF := true)) + SKIP_METAINF := true, \ +)) $(US_EXPORT_POLICY_JAR_LIMITED): \ $(US_EXPORT_POLICY_JAR_UNLIMITED) @@ -122,7 +123,7 @@ LOCAL_POLICY_JAR_UNLIMITED := \ $(SUPPORT_OUTPUTDIR)/jce/policy/unlimited/local_policy.jar # -# TODO fix so that SetupArchive does not write files into SRCS +# TODO fix so that SetupJarArchive does not write files into SRCS # then we don't need this extra copying # LOCAL_POLICY_JAR_LIMITED_TMP := \ @@ -138,22 +139,24 @@ $(LOCAL_POLICY_JAR_UNLIMITED_TMP)/%: \ $(JDK_TOPDIR)/make/data/cryptopolicy/unlimited/% $(install-file) -$(eval $(call SetupArchive,BUILD_LOCAL_POLICY_JAR_LIMITED, \ +$(eval $(call SetupJarArchive, BUILD_LOCAL_POLICY_JAR_LIMITED, \ DEPENDENCIES := $(LOCAL_POLICY_JAR_LIMITED_TMP)/exempt_local.policy \ $(LOCAL_POLICY_JAR_LIMITED_TMP)/default_local.policy, \ SRCS := $(LOCAL_POLICY_JAR_LIMITED_TMP), \ SUFFIXES := .policy, \ JAR := $(LOCAL_POLICY_JAR_LIMITED), \ EXTRA_MANIFEST_ATTR := Crypto-Strength: limited, \ - SKIP_METAINF := true)) + SKIP_METAINF := true, \ +)) -$(eval $(call SetupArchive,BUILD_LOCAL_POLICY_JAR_UNLIMITED, \ +$(eval $(call SetupJarArchive, BUILD_LOCAL_POLICY_JAR_UNLIMITED, \ DEPENDENCIES := $(LOCAL_POLICY_JAR_UNLIMITED_TMP)/default_local.policy, \ SRCS := $(LOCAL_POLICY_JAR_UNLIMITED_TMP), \ SUFFIXES := .policy, \ JAR := $(LOCAL_POLICY_JAR_UNLIMITED), \ EXTRA_MANIFEST_ATTR := Crypto-Strength: unlimited, \ - SKIP_METAINF := true)) + SKIP_METAINF := true, \ +)) TARGETS += $(LOCAL_POLICY_JAR_LIMITED) $(LOCAL_POLICY_JAR_UNLIMITED) From 03a416db62e77e75ad03869109efbd89017a7e35 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 3 Nov 2015 17:41:38 -0800 Subject: [PATCH 21/31] 8141368: Typo in java/lang/Class/IsEnum.java test Reviewed-by: jjg --- jdk/test/java/lang/Class/IsEnum.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/jdk/test/java/lang/Class/IsEnum.java b/jdk/test/java/lang/Class/IsEnum.java index 355f944e607..55175cf10be 100644 --- a/jdk/test/java/lang/Class/IsEnum.java +++ b/jdk/test/java/lang/Class/IsEnum.java @@ -32,8 +32,8 @@ import java.lang.annotation.*; public class IsEnum { - static int test(Class clazz, boolean expected) { - int status = (clazz.isEnum() == expected)?0:1; + static int test(Class clazz, boolean expected) { + int status = (clazz.isEnum() == expected) ? 0 : 1; if (status == 1) { System.err.println("Unexpected enum status for " + clazz); @@ -41,23 +41,23 @@ public class IsEnum { return status; } - public static void main(String argv[]) { + public static void main(String... argv) { int failures = 0; failures += test(IsEnum.class, false); failures += test(String.class, false); failures += test(Enum.class, false); + failures += test(EnumPoseur.class, false); failures += test(java.math.RoundingMode.class, true); - // Classes in java.lang.annoation + // Classes in java.lang.annotation failures += test(Annotation.class, false); failures += test(ElementType.class, true); failures += test(Retention.class, false); failures += test(RetentionPolicy.class, true); failures += test(Target.class, false); - failures += test(EnumPoseur.class, false); - // Classes for specialized enum constants aren't enum's + // A class for a specialized enum constant isn't itself an enum failures += test(SpecialEnum.class, true); failures += test(SpecialEnum.RED.getClass(), false); failures += test(SpecialEnum.GREEN.getClass(), true); From 01355aa18c0cd88becc19604afd2c638df8f28cb Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Wed, 4 Nov 2015 12:46:05 +0100 Subject: [PATCH 22/31] 8141290: AIX: fix build after '8140661: Rename LDFLAGS_SUFFIX to LIBS' Reviewed-by: ihse --- jdk/make/lib/Awt2dLibraries.gmk | 4 ++-- jdk/make/lib/Lib-java.instrument.gmk | 5 +++-- jdk/make/lib/Lib-jdk.jdwp.agent.gmk | 5 +++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/jdk/make/lib/Awt2dLibraries.gmk b/jdk/make/lib/Awt2dLibraries.gmk index 7a26bbfc304..ad60e8a8146 100644 --- a/jdk/make/lib/Awt2dLibraries.gmk +++ b/jdk/make/lib/Awt2dLibraries.gmk @@ -890,9 +890,9 @@ ifndef BUILD_HEADLESS_ONLY MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libsplashscreen/mapfile-vers, \ LDFLAGS := $(LIBSPLASHSCREEN_LDFLAGS) $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ - LIBS := $(LIBSPLASHSCREEN_LIBS) $(LIBZ) \ + LIBS := $(JDKLIB_LIBS) $(LIBSPLASHSCREEN_LIBS) $(LIBZ) \ $(GIFLIB_LIBS) $(LIBJPEG_LIBS) $(PNG_LIBS), \ - LIBS_solaris := -lc, \ + LIBS_aix := -liconv, \ VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \ RC_FLAGS := $(RC_FLAGS) \ -D "JDK_FNAME=splashscreen.dll" \ diff --git a/jdk/make/lib/Lib-java.instrument.gmk b/jdk/make/lib/Lib-java.instrument.gmk index 5b4eacc4703..76ff764ed36 100644 --- a/jdk/make/lib/Lib-java.instrument.gmk +++ b/jdk/make/lib/Lib-java.instrument.gmk @@ -68,10 +68,11 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBINSTRUMENT, \ LDFLAGS_macosx := -Xlinker -all_load $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a, \ LDFLAGS_aix := -L$(SUPPORT_OUTPUTDIR)/native/java.base, \ LDFLAGS_windows := -export:Agent_OnAttach, \ + LIBS := $(JDKLIB_LIBS), \ LIBS_unix := -ljava $(LIBZ), \ LIBS_linux := -ljli $(LIBDL), \ - LIBS_solaris := -ljli $(LIBDL) -lc, \ - LIBS_aix := -ljli_static $(LIBDL),\ + LIBS_solaris := -ljli $(LIBDL), \ + LIBS_aix := -liconv -ljli_static $(LIBDL), \ LIBS_macosx := -liconv -framework Cocoa -framework Security \ -framework ApplicationServices, \ LIBS_windows := $(WIN_JAVA_LIB) advapi32.lib \ diff --git a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk index da2df699f52..504df6dd4d0 100644 --- a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk +++ b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk @@ -84,10 +84,11 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJDWP, \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjdwp/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ + LIBS := $(JDKLIB_LIBS), \ LIBS_linux := $(LIBDL), \ - LIBS_solaris := $(LIBDL) -lc, \ + LIBS_solaris := $(LIBDL), \ LIBS_macosx := -liconv, \ - LIBS_windows := $(JDKLIB_LIBS), \ + LIBS_aix := -liconv, \ VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \ RC_FLAGS := $(RC_FLAGS) \ -D "JDK_FNAME=jdwp.dll" \ From b6f45b188974f26347646e207f8cf9e157be4625 Mon Sep 17 00:00:00 2001 From: Paul Sandoz Date: Wed, 4 Nov 2015 16:44:38 +0100 Subject: [PATCH 23/31] 8033148: Lexicographic comparators for arrays Reviewed-by: jrose, chegar, bchristi, mduigou --- .../share/classes/java/lang/Byte.java | 16 + .../share/classes/java/lang/Short.java | 16 + .../share/classes/java/util/Arrays.java | 3719 ++++++++++++++++- .../java/util/Arrays/ArraysEqCmpTest.java | 1083 +++++ 4 files changed, 4823 insertions(+), 11 deletions(-) create mode 100644 jdk/test/java/util/Arrays/ArraysEqCmpTest.java diff --git a/jdk/src/java.base/share/classes/java/lang/Byte.java b/jdk/src/java.base/share/classes/java/lang/Byte.java index 0ae3903ca7e..51f687cb389 100644 --- a/jdk/src/java.base/share/classes/java/lang/Byte.java +++ b/jdk/src/java.base/share/classes/java/lang/Byte.java @@ -462,6 +462,22 @@ public final class Byte extends Number implements Comparable { return x - y; } + /** + * Compares two {@code byte} values numerically treating the values + * as unsigned. + * + * @param x the first {@code byte} to compare + * @param y the second {@code byte} to compare + * @return the value {@code 0} if {@code x == y}; a value less + * than {@code 0} if {@code x < y} as unsigned values; and + * a value greater than {@code 0} if {@code x > y} as + * unsigned values + * @since 9 + */ + public static int compareUnsigned(byte x, byte y) { + return Byte.toUnsignedInt(x) - Byte.toUnsignedInt(y); + } + /** * Converts the argument to an {@code int} by an unsigned * conversion. In an unsigned conversion to an {@code int}, the diff --git a/jdk/src/java.base/share/classes/java/lang/Short.java b/jdk/src/java.base/share/classes/java/lang/Short.java index 6cc4d17d35a..9fa79f3d8c2 100644 --- a/jdk/src/java.base/share/classes/java/lang/Short.java +++ b/jdk/src/java.base/share/classes/java/lang/Short.java @@ -467,6 +467,22 @@ public final class Short extends Number implements Comparable { return x - y; } + /** + * Compares two {@code short} values numerically treating the values + * as unsigned. + * + * @param x the first {@code short} to compare + * @param y the second {@code short} to compare + * @return the value {@code 0} if {@code x == y}; a value less + * than {@code 0} if {@code x < y} as unsigned values; and + * a value greater than {@code 0} if {@code x > y} as + * unsigned values + * @since 9 + */ + public static int compareUnsigned(short x, short y) { + return Short.toUnsignedInt(x) - Short.toUnsignedInt(y); + } + /** * The number of bits used to represent a {@code short} value in two's * complement binary form. diff --git a/jdk/src/java.base/share/classes/java/util/Arrays.java b/jdk/src/java.base/share/classes/java/util/Arrays.java index 35962987cc8..f18180ac84d 100644 --- a/jdk/src/java.base/share/classes/java/util/Arrays.java +++ b/jdk/src/java.base/share/classes/java/util/Arrays.java @@ -25,6 +25,8 @@ package java.util; +import jdk.internal.HotSpotIntrinsicCandidate; + import java.lang.reflect.Array; import java.util.concurrent.ForkJoinPool; import java.util.function.BinaryOperator; @@ -42,7 +44,6 @@ import java.util.stream.IntStream; import java.util.stream.LongStream; import java.util.stream.Stream; import java.util.stream.StreamSupport; -import jdk.internal.HotSpotIntrinsicCandidate; /** * This class contains various methods for manipulating arrays (such as @@ -2585,6 +2586,55 @@ public class Arrays { return true; } + /** + * Returns true if the two specified arrays of longs, over the specified + * ranges, are equal to one another. + * + *

    Two arrays are considered equal if the number of elements covered by + * each range is the same, and all corresponding pairs of elements over the + * specified ranges in the two arrays are equal. In other words, two arrays + * are equal if they contain, over the specified ranges, the same elements + * in the same order. + * + * @param a the first array to be tested for equality + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested fro equality + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @return {@code true} if the two arrays, over the specified ranges, are + * equal + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static boolean equals(long[] a, int aFromIndex, int aToIndex, + long[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + if (aLength != bLength) + return false; + + for (int i = 0; i < aLength; i++) + if (a[aFromIndex++] != b[bFromIndex++]) + return false; + + return true; + } + /** * Returns {@code true} if the two specified arrays of ints are * equal to one another. Two arrays are considered equal if both @@ -2614,6 +2664,55 @@ public class Arrays { return true; } + /** + * Returns true if the two specified arrays of ints, over the specified + * ranges, are equal to one another. + * + *

    Two arrays are considered equal if the number of elements covered by + * each range is the same, and all corresponding pairs of elements over the + * specified ranges in the two arrays are equal. In other words, two arrays + * are equal if they contain, over the specified ranges, the same elements + * in the same order. + * + * @param a the first array to be tested for equality + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested fro equality + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @return {@code true} if the two arrays, over the specified ranges, are + * equal + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static boolean equals(int[] a, int aFromIndex, int aToIndex, + int[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + if (aLength != bLength) + return false; + + for (int i = 0; i < aLength; i++) + if (a[aFromIndex++] != b[bFromIndex++]) + return false; + + return true; + } + /** * Returns {@code true} if the two specified arrays of shorts are * equal to one another. Two arrays are considered equal if both @@ -2643,6 +2742,55 @@ public class Arrays { return true; } + /** + * Returns true if the two specified arrays of shorts, over the specified + * ranges, are equal to one another. + * + *

    Two arrays are considered equal if the number of elements covered by + * each range is the same, and all corresponding pairs of elements over the + * specified ranges in the two arrays are equal. In other words, two arrays + * are equal if they contain, over the specified ranges, the same elements + * in the same order. + * + * @param a the first array to be tested for equality + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested fro equality + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @return {@code true} if the two arrays, over the specified ranges, are + * equal + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static boolean equals(short[] a, int aFromIndex, int aToIndex, + short[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + if (aLength != bLength) + return false; + + for (int i = 0; i < aLength; i++) + if (a[aFromIndex++] != b[bFromIndex++]) + return false; + + return true; + } + /** * Returns {@code true} if the two specified arrays of chars are * equal to one another. Two arrays are considered equal if both @@ -2673,6 +2821,55 @@ public class Arrays { return true; } + /** + * Returns true if the two specified arrays of chars, over the specified + * ranges, are equal to one another. + * + *

    Two arrays are considered equal if the number of elements covered by + * each range is the same, and all corresponding pairs of elements over the + * specified ranges in the two arrays are equal. In other words, two arrays + * are equal if they contain, over the specified ranges, the same elements + * in the same order. + * + * @param a the first array to be tested for equality + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested fro equality + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @return {@code true} if the two arrays, over the specified ranges, are + * equal + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static boolean equals(char[] a, int aFromIndex, int aToIndex, + char[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + if (aLength != bLength) + return false; + + for (int i = 0; i < aLength; i++) + if (a[aFromIndex++] != b[bFromIndex++]) + return false; + + return true; + } + /** * Returns {@code true} if the two specified arrays of bytes are * equal to one another. Two arrays are considered equal if both @@ -2702,6 +2899,55 @@ public class Arrays { return true; } + /** + * Returns true if the two specified arrays of bytes, over the specified + * ranges, are equal to one another. + * + *

    Two arrays are considered equal if the number of elements covered by + * each range is the same, and all corresponding pairs of elements over the + * specified ranges in the two arrays are equal. In other words, two arrays + * are equal if they contain, over the specified ranges, the same elements + * in the same order. + * + * @param a the first array to be tested for equality + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested fro equality + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @return {@code true} if the two arrays, over the specified ranges, are + * equal + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static boolean equals(byte[] a, int aFromIndex, int aToIndex, + byte[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + if (aLength != bLength) + return false; + + for (int i = 0; i < aLength; i++) + if (a[aFromIndex++] != b[bFromIndex++]) + return false; + + return true; + } + /** * Returns {@code true} if the two specified arrays of booleans are * equal to one another. Two arrays are considered equal if both @@ -2731,6 +2977,55 @@ public class Arrays { return true; } + /** + * Returns true if the two specified arrays of booleans, over the specified + * ranges, are equal to one another. + * + *

    Two arrays are considered equal if the number of elements covered by + * each range is the same, and all corresponding pairs of elements over the + * specified ranges in the two arrays are equal. In other words, two arrays + * are equal if they contain, over the specified ranges, the same elements + * in the same order. + * + * @param a the first array to be tested for equality + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested fro equality + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @return {@code true} if the two arrays, over the specified ranges, are + * equal + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static boolean equals(boolean[] a, int aFromIndex, int aToIndex, + boolean[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + if (aLength != bLength) + return false; + + for (int i = 0; i < aLength; i++) + if (a[aFromIndex++] != b[bFromIndex++]) + return false; + + return true; + } + /** * Returns {@code true} if the two specified arrays of doubles are * equal to one another. Two arrays are considered equal if both @@ -2759,9 +3054,70 @@ public class Arrays { if (a2.length != length) return false; - for (int i=0; iequal to one another. + * + *

    Two arrays are considered equal if the number of elements covered by + * each range is the same, and all corresponding pairs of elements over the + * specified ranges in the two arrays are equal. In other words, two arrays + * are equal if they contain, over the specified ranges, the same elements + * in the same order. + * + *

    Two doubles {@code d1} and {@code d2} are considered equal if: + *

        {@code new Double(d1).equals(new Double(d2))}
    + * (Unlike the {@code ==} operator, this method considers + * {@code NaN} equals to itself, and 0.0d unequal to -0.0d.) + * + * @param a the first array to be tested for equality + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested fro equality + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @return {@code true} if the two arrays, over the specified ranges, are + * equal + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @see Double#equals(Object) + * @since 9 + */ + public static boolean equals(double[] a, int aFromIndex, int aToIndex, + double[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + if (aLength != bLength) + return false; + + for (int i = 0; i < aLength; i++) { + Double va = a[aFromIndex++], vb = b[bFromIndex++]; + if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb)) + if (!Double.isNaN(va) || !Double.isNaN(vb)) + return false; + } return true; } @@ -2794,9 +3150,70 @@ public class Arrays { if (a2.length != length) return false; - for (int i=0; iequal to one another. + * + *

    Two arrays are considered equal if the number of elements covered by + * each range is the same, and all corresponding pairs of elements over the + * specified ranges in the two arrays are equal. In other words, two arrays + * are equal if they contain, over the specified ranges, the same elements + * in the same order. + * + *

    Two floats {@code f1} and {@code f2} are considered equal if: + *

        {@code new Float(f1).equals(new Float(f2))}
    + * (Unlike the {@code ==} operator, this method considers + * {@code NaN} equals to itself, and 0.0f unequal to -0.0f.) + * + * @param a the first array to be tested for equality + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested fro equality + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @return {@code true} if the two arrays, over the specified ranges, are + * equal + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @see Float#equals(Object) + * @since 9 + */ + public static boolean equals(float[] a, int aFromIndex, int aToIndex, + float[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + if (aLength != bLength) + return false; + + for (int i = 0; i < aLength; i++) { + float va = a[aFromIndex++], vb = b[bFromIndex++]; + if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb)) + if (!Float.isNaN(va) || !Float.isNaN(vb)) + return false; + } return true; } @@ -2827,9 +3244,60 @@ public class Arrays { return false; for (int i=0; iequal to one another. + * + *

    Two arrays are considered equal if the number of elements covered by + * each range is the same, and all corresponding pairs of elements over the + * specified ranges in the two arrays are equal. In other words, two arrays + * are equal if they contain, over the specified ranges, the same elements + * in the same order. + * + *

    Two objects {@code e1} and {@code e2} are considered equal if + * {@code Objects.equals(e1, e2)}. + * + * @param a the first array to be tested for equality + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested fro equality + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @return {@code true} if the two arrays, over the specified ranges, are + * equal + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static boolean equals(Object[] a, int aFromIndex, int aToIndex, + Object[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + if (aLength != bLength) + return false; + + for (int i = 0; i < aLength; i++) { + if (!Objects.equals(a[aFromIndex++], b[bFromIndex++])) return false; } @@ -5185,4 +5653,3233 @@ public class Arrays { public static DoubleStream stream(double[] array, int startInclusive, int endExclusive) { return StreamSupport.doubleStream(spliterator(array, startInclusive, endExclusive), false); } -} + + + // Comparison methods + + // Compare boolean + + /** + * Compares two {@code boolean} arrays lexicographically. + * + *

    If the two arrays share a common prefix then the lexicographic + * comparison is the result of comparing two elements, as if by + * {@link Boolean#compare(boolean, boolean)}, at an index within the + * respective arrays that is the prefix length. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two array lengths. + * (See {@link #mismatch(boolean[], boolean[])} for the definition of a + * common and proper prefix.) + * + *

    A {@code null} array reference is considered lexicographically less + * than a non-{@code null} array reference. Two {@code null} array + * references are considered equal. + * + *

    The comparison is consistent with {@link #equals(boolean[], boolean[]) equals}, + * more specifically the following holds for arrays {@code a} and {@code b}: + *

    {@code
    +     *     Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
    +     * }
    + * + * @apiNote + *

    This method behaves as if (for non-{@code null} array references): + *

    {@code
    +     *     int i = Arrays.mismatch(a, b);
    +     *     if (i >= 0 && i < Math.min(a.length, b.length))
    +     *         return Boolean.compare(a[i], b[i]);
    +     *     return a.length - b.length;
    +     * }
    + * + * @param a the first array to compare + * @param b the second array to compare + * @return the value {@code 0} if the first and second array are equal and + * contain the same elements in the same order; + * a value less than {@code 0} if the first array is + * lexicographically less than the second array; and + * a value greater than {@code 0} if the first array is + * lexicographically greater than the second array + * @since 9 + */ + public static int compare(boolean[] a, boolean[] b) { + if (a == b) + return 0; + if (a == null || b == null) + return a == null ? -1 : 1; + + int length = Math.min(a.length, b.length); + for (int i = 0; i < length; i++) { + if (a[i] != b[i]) return Boolean.compare(a[i], b[i]); + } + + return a.length - b.length; + } + + /** + * Compares two {@code boolean} arrays lexicographically over the specified + * ranges. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the lexicographic comparison is the result of comparing two + * elements, as if by {@link Boolean#compare(boolean, boolean)}, at a + * relative index within the respective arrays that is the length of the + * prefix. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two range lengths. + * (See {@link #mismatch(boolean[], int, int, boolean[], int, int)} for the + * definition of a common and proper prefix.) + * + *

    The comparison is consistent with + * {@link #equals(boolean[], int, int, boolean[], int, int) equals}, more + * specifically the following holds for arrays {@code a} and {@code b} with + * specified ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively: + *

    {@code
    +     *     Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
    +     *         (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
    +     * }
    + * + * @apiNote + *

    This method behaves as if: + *

    {@code
    +     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
    +     *                             b, bFromIndex, bToIndex);
    +     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     *         return Boolean.compare(a[aFromIndex + i], b[bFromIndex + i]);
    +     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
    +     * }
    + * + * @param a the first array to compare + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be compared + * @param aToIndex the index (exclusive) of the last element in the + * first array to be compared + * @param b the second array to compare + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be compared + * @param bToIndex the index (exclusive) of the last element in the + * second array to be compared + * @return the value {@code 0} if, over the specified ranges, the first and + * second array are equal and contain the same elements in the same + * order; + * a value less than {@code 0} if, over the specified ranges, the + * first array is lexicographically less than the second array; and + * a value greater than {@code 0} if, over the specified ranges, the + * first array is lexicographically greater than the second array + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int compare(boolean[] a, int aFromIndex, int aToIndex, + boolean[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + boolean va = a[aFromIndex++]; + boolean vb = b[bFromIndex++]; + if (va != vb) return Boolean.compare(va, vb); + } + + return aLength - bLength; + } + + // Compare byte + + /** + * Compares two {@code byte} arrays lexicographically. + * + *

    If the two arrays share a common prefix then the lexicographic + * comparison is the result of comparing two elements, as if by + * {@link Byte#compare(byte, byte)}, at an index within the respective + * arrays that is the prefix length. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two array lengths. + * (See {@link #mismatch(byte[], byte[])} for the definition of a common and + * proper prefix.) + * + *

    A {@code null} array reference is considered lexicographically less + * than a non-{@code null} array reference. Two {@code null} array + * references are considered equal. + * + *

    The comparison is consistent with {@link #equals(byte[], byte[]) equals}, + * more specifically the following holds for arrays {@code a} and {@code b}: + *

    {@code
    +     *     Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
    +     * }
    + * + * @apiNote + *

    This method behaves as if (for non-{@code null} array references): + *

    {@code
    +     *     int i = Arrays.mismatch(a, b);
    +     *     if (i >= 0 && i < Math.min(a.length, b.length))
    +     *         return Byte.compare(a[i], b[i]);
    +     *     return a.length - b.length;
    +     * }
    + * + * @param a the first array to compare + * @param b the second array to compare + * @return the value {@code 0} if the first and second array are equal and + * contain the same elements in the same order; + * a value less than {@code 0} if the first array is + * lexicographically less than the second array; and + * a value greater than {@code 0} if the first array is + * lexicographically greater than the second array + * @since 9 + */ + public static int compare(byte[] a, byte[] b) { + if (a == b) + return 0; + if (a == null || b == null) + return a == null ? -1 : 1; + + int length = Math.min(a.length, b.length); + for (int i = 0; i < length; i++) { + if (a[i] != b[i]) return Byte.compare(a[i], b[i]); + } + + return a.length - b.length; + } + + /** + * Compares two {@code byte} arrays lexicographically over the specified + * ranges. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the lexicographic comparison is the result of comparing two + * elements, as if by {@link Byte#compare(byte, byte)}, at a relative index + * within the respective arrays that is the length of the prefix. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two range lengths. + * (See {@link #mismatch(byte[], int, int, byte[], int, int)} for the + * definition of a common and proper prefix.) + * + *

    The comparison is consistent with + * {@link #equals(byte[], int, int, byte[], int, int) equals}, more + * specifically the following holds for arrays {@code a} and {@code b} with + * specified ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively: + *

    {@code
    +     *     Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
    +     *         (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
    +     * }
    + * + * @apiNote + *

    This method behaves as if: + *

    {@code
    +     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
    +     *                             b, bFromIndex, bToIndex);
    +     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     *         return Byte.compare(a[aFromIndex + i], b[bFromIndex + i]);
    +     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
    +     * }
    + * + * @param a the first array to compare + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be compared + * @param aToIndex the index (exclusive) of the last element in the + * first array to be compared + * @param b the second array to compare + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be compared + * @param bToIndex the index (exclusive) of the last element in the + * second array to be compared + * @return the value {@code 0} if, over the specified ranges, the first and + * second array are equal and contain the same elements in the same + * order; + * a value less than {@code 0} if, over the specified ranges, the + * first array is lexicographically less than the second array; and + * a value greater than {@code 0} if, over the specified ranges, the + * first array is lexicographically greater than the second array + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int compare(byte[] a, int aFromIndex, int aToIndex, + byte[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + byte va = a[aFromIndex++]; + byte vb = b[bFromIndex++]; + if (va != vb) return Byte.compare(va, vb); + } + + return aLength - bLength; + } + + /** + * Compares two {@code byte} arrays lexicographically, numerically treating + * elements as unsigned. + * + *

    If the two arrays share a common prefix then the lexicographic + * comparison is the result of comparing two elements, as if by + * {@link Byte#compareUnsigned(byte, byte)}, at an index within the + * respective arrays that is the prefix length. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two array lengths. + * (See {@link #mismatch(byte[], byte[])} for the definition of a common + * and proper prefix.) + * + *

    A {@code null} array reference is considered lexicographically less + * than a non-{@code null} array reference. Two {@code null} array + * references are considered equal. + * + * @apiNote + *

    This method behaves as if (for non-{@code null} array references): + *

    {@code
    +     *     int i = Arrays.mismatch(a, b);
    +     *     if (i >= 0 && i < Math.min(a.length, b.length))
    +     *         return Byte.compareUnsigned(a[i], b[i]);
    +     *     return a.length - b.length;
    +     * }
    + * + * @param a the first array to compare + * @param b the second array to compare + * @return the value {@code 0} if the first and second array are + * equal and contain the same elements in the same order; + * a value less than {@code 0} if the first array is + * lexicographically less than the second array; and + * a value greater than {@code 0} if the first array is + * lexicographically greater than the second array + * @since 9 + */ + public static int compareUnsigned(byte[] a, byte[] b) { + if (a == b) + return 0; + if (a == null || b == null) + return a == null ? -1 : 1; + + int length = Math.min(a.length, b.length); + for (int i = 0; i < length; i++) { + if (a[i] != b[i]) return Byte.compareUnsigned(a[i], b[i]); + } + + return a.length - b.length; + } + + + /** + * Compares two {@code byte} arrays lexicographically over the specified + * ranges, numerically treating elements as unsigned. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the lexicographic comparison is the result of comparing two + * elements, as if by {@link Byte#compareUnsigned(byte, byte)}, at a + * relative index within the respective arrays that is the length of the + * prefix. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two range lengths. + * (See {@link #mismatch(byte[], int, int, byte[], int, int)} for the + * definition of a common and proper prefix.) + * + * @apiNote + *

    This method behaves as if: + *

    {@code
    +     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
    +     *                             b, bFromIndex, bToIndex);
    +     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     *         return Byte.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
    +     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
    +     * }
    + * + * @param a the first array to compare + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be compared + * @param aToIndex the index (exclusive) of the last element in the + * first array to be compared + * @param b the second array to compare + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be compared + * @param bToIndex the index (exclusive) of the last element in the + * second array to be compared + * @return the value {@code 0} if, over the specified ranges, the first and + * second array are equal and contain the same elements in the same + * order; + * a value less than {@code 0} if, over the specified ranges, the + * first array is lexicographically less than the second array; and + * a value greater than {@code 0} if, over the specified ranges, the + * first array is lexicographically greater than the second array + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is null + * @since 9 + */ + public static int compareUnsigned(byte[] a, int aFromIndex, int aToIndex, + byte[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + byte va = a[aFromIndex++]; + byte vb = b[bFromIndex++]; + if (va != vb) return Byte.compareUnsigned(va, vb); + } + + return aLength - bLength; + } + + // Compare short + + /** + * Compares two {@code short} arrays lexicographically. + * + *

    If the two arrays share a common prefix then the lexicographic + * comparison is the result of comparing two elements, as if by + * {@link Short#compare(short, short)}, at an index within the respective + * arrays that is the prefix length. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two array lengths. + * (See {@link #mismatch(short[], short[])} for the definition of a common + * and proper prefix.) + * + *

    A {@code null} array reference is considered lexicographically less + * than a non-{@code null} array reference. Two {@code null} array + * references are considered equal. + * + *

    The comparison is consistent with {@link #equals(short[], short[]) equals}, + * more specifically the following holds for arrays {@code a} and {@code b}: + *

    {@code
    +     *     Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
    +     * }
    + * + * @apiNote + *

    This method behaves as if (for non-{@code null} array references): + *

    {@code
    +     *     int i = Arrays.mismatch(a, b);
    +     *     if (i >= 0 && i < Math.min(a.length, b.length))
    +     *         return Short.compare(a[i], b[i]);
    +     *     return a.length - b.length;
    +     * }
    + * + * @param a the first array to compare + * @param b the second array to compare + * @return the value {@code 0} if the first and second array are equal and + * contain the same elements in the same order; + * a value less than {@code 0} if the first array is + * lexicographically less than the second array; and + * a value greater than {@code 0} if the first array is + * lexicographically greater than the second array + * @since 9 + */ + public static int compare(short[] a, short[] b) { + if (a == b) + return 0; + if (a == null || b == null) + return a == null ? -1 : 1; + + int length = Math.min(a.length, b.length); + for (int i = 0; i < length; i++) { + if (a[i] != b[i]) return Short.compare(a[i], b[i]); + } + + return a.length - b.length; + } + + /** + * Compares two {@code short} arrays lexicographically over the specified + * ranges. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the lexicographic comparison is the result of comparing two + * elements, as if by {@link Short#compare(short, short)}, at a relative + * index within the respective arrays that is the length of the prefix. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two range lengths. + * (See {@link #mismatch(short[], int, int, short[], int, int)} for the + * definition of a common and proper prefix.) + * + *

    The comparison is consistent with + * {@link #equals(short[], int, int, short[], int, int) equals}, more + * specifically the following holds for arrays {@code a} and {@code b} with + * specified ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively: + *

    {@code
    +     *     Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
    +     *         (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
    +     * }
    + * + * @apiNote + *

    This method behaves as if: + *

    {@code
    +     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
    +     *                             b, bFromIndex, bToIndex);
    +     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     *         return Short.compare(a[aFromIndex + i], b[bFromIndex + i]);
    +     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
    +     * }
    + * + * @param a the first array to compare + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be compared + * @param aToIndex the index (exclusive) of the last element in the + * first array to be compared + * @param b the second array to compare + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be compared + * @param bToIndex the index (exclusive) of the last element in the + * second array to be compared + * @return the value {@code 0} if, over the specified ranges, the first and + * second array are equal and contain the same elements in the same + * order; + * a value less than {@code 0} if, over the specified ranges, the + * first array is lexicographically less than the second array; and + * a value greater than {@code 0} if, over the specified ranges, the + * first array is lexicographically greater than the second array + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int compare(short[] a, int aFromIndex, int aToIndex, + short[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + short va = a[aFromIndex++]; + short vb = b[bFromIndex++]; + if (va != vb) return Short.compare(va, vb); + } + + return aLength - bLength; + } + + /** + * Compares two {@code short} arrays lexicographically, numerically treating + * elements as unsigned. + * + *

    If the two arrays share a common prefix then the lexicographic + * comparison is the result of comparing two elements, as if by + * {@link Short#compareUnsigned(short, short)}, at an index within the + * respective arrays that is the prefix length. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two array lengths. + * (See {@link #mismatch(short[], short[])} for the definition of a common + * and proper prefix.) + * + *

    A {@code null} array reference is considered lexicographically less + * than a non-{@code null} array reference. Two {@code null} array + * references are considered equal. + * + * @apiNote + *

    This method behaves as if (for non-{@code null} array references): + *

    {@code
    +     *     int i = Arrays.mismatch(a, b);
    +     *     if (i >= 0 && i < Math.min(a.length, b.length))
    +     *         return Short.compareUnsigned(a[i], b[i]);
    +     *     return a.length - b.length;
    +     * }
    + * + * @param a the first array to compare + * @param b the second array to compare + * @return the value {@code 0} if the first and second array are + * equal and contain the same elements in the same order; + * a value less than {@code 0} if the first array is + * lexicographically less than the second array; and + * a value greater than {@code 0} if the first array is + * lexicographically greater than the second array + * @since 9 + */ + public static int compareUnsigned(short[] a, short[] b) { + if (a == b) + return 0; + if (a == null || b == null) + return a == null ? -1 : 1; + + int length = Math.min(a.length, b.length); + for (int i = 0; i < length; i++) { + if (a[i] != b[i]) return Short.compareUnsigned(a[i], b[i]); + } + + return a.length - b.length; + } + + /** + * Compares two {@code short} arrays lexicographically over the specified + * ranges, numerically treating elements as unsigned. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the lexicographic comparison is the result of comparing two + * elements, as if by {@link Short#compareUnsigned(short, short)}, at a + * relative index within the respective arrays that is the length of the + * prefix. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two range lengths. + * (See {@link #mismatch(short[], int, int, short[], int, int)} for the + * definition of a common and proper prefix.) + * + * @apiNote + *

    This method behaves as if: + *

    {@code
    +     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
    +     *                             b, bFromIndex, bToIndex);
    +     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     *         return Short.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
    +     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
    +     * }
    + * + * @param a the first array to compare + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be compared + * @param aToIndex the index (exclusive) of the last element in the + * first array to be compared + * @param b the second array to compare + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be compared + * @param bToIndex the index (exclusive) of the last element in the + * second array to be compared + * @return the value {@code 0} if, over the specified ranges, the first and + * second array are equal and contain the same elements in the same + * order; + * a value less than {@code 0} if, over the specified ranges, the + * first array is lexicographically less than the second array; and + * a value greater than {@code 0} if, over the specified ranges, the + * first array is lexicographically greater than the second array + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is null + * @since 9 + */ + public static int compareUnsigned(short[] a, int aFromIndex, int aToIndex, + short[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + short va = a[aFromIndex++]; + short vb = b[bFromIndex++]; + if (va != vb) return Short.compareUnsigned(va, vb); + } + + return aLength - bLength; + } + + // Compare char + + /** + * Compares two {@code char} arrays lexicographically. + * + *

    If the two arrays share a common prefix then the lexicographic + * comparison is the result of comparing two elements, as if by + * {@link Character#compare(char, char)}, at an index within the respective + * arrays that is the prefix length. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two array lengths. + * (See {@link #mismatch(char[], char[])} for the definition of a common and + * proper prefix.) + * + *

    A {@code null} array reference is considered lexicographically less + * than a non-{@code null} array reference. Two {@code null} array + * references are considered equal. + * + *

    The comparison is consistent with {@link #equals(char[], char[]) equals}, + * more specifically the following holds for arrays {@code a} and {@code b}: + *

    {@code
    +     *     Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
    +     * }
    + * + * @apiNote + *

    This method behaves as if (for non-{@code null} array references): + *

    {@code
    +     *     int i = Arrays.mismatch(a, b);
    +     *     if (i >= 0 && i < Math.min(a.length, b.length))
    +     *         return Character.compare(a[i], b[i]);
    +     *     return a.length - b.length;
    +     * }
    + * + * @param a the first array to compare + * @param b the second array to compare + * @return the value {@code 0} if the first and second array are equal and + * contain the same elements in the same order; + * a value less than {@code 0} if the first array is + * lexicographically less than the second array; and + * a value greater than {@code 0} if the first array is + * lexicographically greater than the second array + * @since 9 + */ + public static int compare(char[] a, char[] b) { + if (a == b) + return 0; + if (a == null || b == null) + return a == null ? -1 : 1; + + int length = Math.min(a.length, b.length); + for (int i = 0; i < length; i++) { + if (a[i] != b[i]) return Character.compare(a[i], b[i]); + } + + return a.length - b.length; + } + + /** + * Compares two {@code char} arrays lexicographically over the specified + * ranges. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the lexicographic comparison is the result of comparing two + * elements, as if by {@link Character#compare(char, char)}, at a relative + * index within the respective arrays that is the length of the prefix. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two range lengths. + * (See {@link #mismatch(char[], int, int, char[], int, int)} for the + * definition of a common and proper prefix.) + * + *

    The comparison is consistent with + * {@link #equals(char[], int, int, char[], int, int) equals}, more + * specifically the following holds for arrays {@code a} and {@code b} with + * specified ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively: + *

    {@code
    +     *     Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
    +     *         (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
    +     * }
    + * + * @apiNote + *

    This method behaves as if: + *

    {@code
    +     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
    +     *                             b, bFromIndex, bToIndex);
    +     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     *         return Character.compare(a[aFromIndex + i], b[bFromIndex + i]);
    +     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
    +     * }
    + * + * @param a the first array to compare + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be compared + * @param aToIndex the index (exclusive) of the last element in the + * first array to be compared + * @param b the second array to compare + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be compared + * @param bToIndex the index (exclusive) of the last element in the + * second array to be compared + * @return the value {@code 0} if, over the specified ranges, the first and + * second array are equal and contain the same elements in the same + * order; + * a value less than {@code 0} if, over the specified ranges, the + * first array is lexicographically less than the second array; and + * a value greater than {@code 0} if, over the specified ranges, the + * first array is lexicographically greater than the second array + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int compare(char[] a, int aFromIndex, int aToIndex, + char[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + char va = a[aFromIndex++]; + char vb = b[bFromIndex++]; + if (va != vb) return Character.compare(va, vb); + } + + return aLength - bLength; + } + + // Compare int + + /** + * Compares two {@code int} arrays lexicographically. + * + *

    If the two arrays share a common prefix then the lexicographic + * comparison is the result of comparing two elements, as if by + * {@link Integer#compare(int, int)}, at an index within the respective + * arrays that is the prefix length. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two array lengths. + * (See {@link #mismatch(int[], int[])} for the definition of a common and + * proper prefix.) + * + *

    A {@code null} array reference is considered lexicographically less + * than a non-{@code null} array reference. Two {@code null} array + * references are considered equal. + * + *

    The comparison is consistent with {@link #equals(int[], int[]) equals}, + * more specifically the following holds for arrays {@code a} and {@code b}: + *

    {@code
    +     *     Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
    +     * }
    + * + * @apiNote + *

    This method behaves as if (for non-{@code null} array references): + *

    {@code
    +     *     int i = Arrays.mismatch(a, b);
    +     *     if (i >= 0 && i < Math.min(a.length, b.length))
    +     *         return Integer.compare(a[i], b[i]);
    +     *     return a.length - b.length;
    +     * }
    + * + * @param a the first array to compare + * @param b the second array to compare + * @return the value {@code 0} if the first and second array are equal and + * contain the same elements in the same order; + * a value less than {@code 0} if the first array is + * lexicographically less than the second array; and + * a value greater than {@code 0} if the first array is + * lexicographically greater than the second array + * @since 9 + */ + public static int compare(int[] a, int[] b) { + if (a == b) + return 0; + if (a == null || b == null) + return a == null ? -1 : 1; + + int length = Math.min(a.length, b.length); + for (int i = 0; i < length; i++) { + if (a[i] != b[i]) return Integer.compare(a[i], b[i]); + } + + return a.length - b.length; + } + + /** + * Compares two {@code int} arrays lexicographically over the specified + * ranges. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the lexicographic comparison is the result of comparing two + * elements, as if by {@link Integer#compare(int, int)}, at a relative index + * within the respective arrays that is the length of the prefix. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two range lengths. + * (See {@link #mismatch(int[], int, int, int[], int, int)} for the + * definition of a common and proper prefix.) + * + *

    The comparison is consistent with + * {@link #equals(int[], int, int, int[], int, int) equals}, more + * specifically the following holds for arrays {@code a} and {@code b} with + * specified ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively: + *

    {@code
    +     *     Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
    +     *         (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
    +     * }
    + * + * @apiNote + *

    This method behaves as if: + *

    {@code
    +     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
    +     *                             b, bFromIndex, bToIndex);
    +     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     *         return Integer.compare(a[aFromIndex + i], b[bFromIndex + i]);
    +     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
    +     * }
    + * + * @param a the first array to compare + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be compared + * @param aToIndex the index (exclusive) of the last element in the + * first array to be compared + * @param b the second array to compare + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be compared + * @param bToIndex the index (exclusive) of the last element in the + * second array to be compared + * @return the value {@code 0} if, over the specified ranges, the first and + * second array are equal and contain the same elements in the same + * order; + * a value less than {@code 0} if, over the specified ranges, the + * first array is lexicographically less than the second array; and + * a value greater than {@code 0} if, over the specified ranges, the + * first array is lexicographically greater than the second array + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int compare(int[] a, int aFromIndex, int aToIndex, + int[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + int va = a[aFromIndex++]; + int vb = b[bFromIndex++]; + if (va != vb) return Integer.compare(va, vb); + } + + return aLength - bLength; + } + + /** + * Compares two {@code int} arrays lexicographically, numerically treating + * elements as unsigned. + * + *

    If the two arrays share a common prefix then the lexicographic + * comparison is the result of comparing two elements, as if by + * {@link Integer#compareUnsigned(int, int)}, at an index within the + * respective arrays that is the prefix length. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two array lengths. + * (See {@link #mismatch(int[], int[])} for the definition of a common + * and proper prefix.) + * + *

    A {@code null} array reference is considered lexicographically less + * than a non-{@code null} array reference. Two {@code null} array + * references are considered equal. + * + * @apiNote + *

    This method behaves as if (for non-{@code null} array references): + *

    {@code
    +     *     int i = Arrays.mismatch(a, b);
    +     *     if (i >= 0 && i < Math.min(a.length, b.length))
    +     *         return Integer.compareUnsigned(a[i], b[i]);
    +     *     return a.length - b.length;
    +     * }
    + * + * @param a the first array to compare + * @param b the second array to compare + * @return the value {@code 0} if the first and second array are + * equal and contain the same elements in the same order; + * a value less than {@code 0} if the first array is + * lexicographically less than the second array; and + * a value greater than {@code 0} if the first array is + * lexicographically greater than the second array + * @since 9 + */ + public static int compareUnsigned(int[] a, int[] b) { + if (a == b) + return 0; + if (a == null || b == null) + return a == null ? -1 : 1; + + int length = Math.min(a.length, b.length); + for (int i = 0; i < length; i++) { + if (a[i] != b[i]) return Integer.compareUnsigned(a[i], b[i]); + } + + return a.length - b.length; + } + + /** + * Compares two {@code int} arrays lexicographically over the specified + * ranges, numerically treating elements as unsigned. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the lexicographic comparison is the result of comparing two + * elements, as if by {@link Integer#compareUnsigned(int, int)}, at a + * relative index within the respective arrays that is the length of the + * prefix. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two range lengths. + * (See {@link #mismatch(int[], int, int, int[], int, int)} for the + * definition of a common and proper prefix.) + * + * @apiNote + *

    This method behaves as if: + *

    {@code
    +     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
    +     *                             b, bFromIndex, bToIndex);
    +     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     *         return Integer.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
    +     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
    +     * }
    + * + * @param a the first array to compare + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be compared + * @param aToIndex the index (exclusive) of the last element in the + * first array to be compared + * @param b the second array to compare + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be compared + * @param bToIndex the index (exclusive) of the last element in the + * second array to be compared + * @return the value {@code 0} if, over the specified ranges, the first and + * second array are equal and contain the same elements in the same + * order; + * a value less than {@code 0} if, over the specified ranges, the + * first array is lexicographically less than the second array; and + * a value greater than {@code 0} if, over the specified ranges, the + * first array is lexicographically greater than the second array + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is null + * @since 9 + */ + public static int compareUnsigned(int[] a, int aFromIndex, int aToIndex, + int[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + int va = a[aFromIndex++]; + int vb = b[bFromIndex++]; + if (va != vb) return Integer.compareUnsigned(va, vb); + } + + return aLength - bLength; + } + + // Compare long + + /** + * Compares two {@code long} arrays lexicographically. + * + *

    If the two arrays share a common prefix then the lexicographic + * comparison is the result of comparing two elements, as if by + * {@link Long#compare(long, long)}, at an index within the respective + * arrays that is the prefix length. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two array lengths. + * (See {@link #mismatch(long[], long[])} for the definition of a common and + * proper prefix.) + * + *

    A {@code null} array reference is considered lexicographically less + * than a non-{@code null} array reference. Two {@code null} array + * references are considered equal. + * + *

    The comparison is consistent with {@link #equals(long[], long[]) equals}, + * more specifically the following holds for arrays {@code a} and {@code b}: + *

    {@code
    +     *     Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
    +     * }
    + * + * @apiNote + *

    This method behaves as if (for non-{@code null} array references): + *

    {@code
    +     *     int i = Arrays.mismatch(a, b);
    +     *     if (i >= 0 && i < Math.min(a.length, b.length))
    +     *         return Long.compare(a[i], b[i]);
    +     *     return a.length - b.length;
    +     * }
    + * + * @param a the first array to compare + * @param b the second array to compare + * @return the value {@code 0} if the first and second array are equal and + * contain the same elements in the same order; + * a value less than {@code 0} if the first array is + * lexicographically less than the second array; and + * a value greater than {@code 0} if the first array is + * lexicographically greater than the second array + * @since 9 + */ + public static int compare(long[] a, long[] b) { + if (a == b) + return 0; + if (a == null || b == null) + return a == null ? -1 : 1; + + int length = Math.min(a.length, b.length); + for (int i = 0; i < length; i++) { + if (a[i] != b[i]) return Long.compare(a[i], b[i]); + } + + return a.length - b.length; + } + + /** + * Compares two {@code long} arrays lexicographically over the specified + * ranges. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the lexicographic comparison is the result of comparing two + * elements, as if by {@link Long#compare(long, long)}, at a relative index + * within the respective arrays that is the length of the prefix. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two range lengths. + * (See {@link #mismatch(long[], int, int, long[], int, int)} for the + * definition of a common and proper prefix.) + * + *

    The comparison is consistent with + * {@link #equals(long[], int, int, long[], int, int) equals}, more + * specifically the following holds for arrays {@code a} and {@code b} with + * specified ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively: + *

    {@code
    +     *     Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
    +     *         (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
    +     * }
    + * + * @apiNote + *

    This method behaves as if: + *

    {@code
    +     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
    +     *                             b, bFromIndex, bToIndex);
    +     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     *         return Long.compare(a[aFromIndex + i], b[bFromIndex + i]);
    +     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
    +     * }
    + * + * @param a the first array to compare + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be compared + * @param aToIndex the index (exclusive) of the last element in the + * first array to be compared + * @param b the second array to compare + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be compared + * @param bToIndex the index (exclusive) of the last element in the + * second array to be compared + * @return the value {@code 0} if, over the specified ranges, the first and + * second array are equal and contain the same elements in the same + * order; + * a value less than {@code 0} if, over the specified ranges, the + * first array is lexicographically less than the second array; and + * a value greater than {@code 0} if, over the specified ranges, the + * first array is lexicographically greater than the second array + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int compare(long[] a, int aFromIndex, int aToIndex, + long[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + long va = a[aFromIndex++]; + long vb = b[bFromIndex++]; + if (va != vb) return Long.compare(va, vb); + } + + return aLength - bLength; + } + + /** + * Compares two {@code long} arrays lexicographically, numerically treating + * elements as unsigned. + * + *

    If the two arrays share a common prefix then the lexicographic + * comparison is the result of comparing two elements, as if by + * {@link Long#compareUnsigned(long, long)}, at an index within the + * respective arrays that is the prefix length. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two array lengths. + * (See {@link #mismatch(long[], long[])} for the definition of a common + * and proper prefix.) + * + *

    A {@code null} array reference is considered lexicographically less + * than a non-{@code null} array reference. Two {@code null} array + * references are considered equal. + * + * @apiNote + *

    This method behaves as if (for non-{@code null} array references): + *

    {@code
    +     *     int i = Arrays.mismatch(a, b);
    +     *     if (i >= 0 && i < Math.min(a.length, b.length))
    +     *         return Long.compareUnsigned(a[i], b[i]);
    +     *     return a.length - b.length;
    +     * }
    + * + * @param a the first array to compare + * @param b the second array to compare + * @return the value {@code 0} if the first and second array are + * equal and contain the same elements in the same order; + * a value less than {@code 0} if the first array is + * lexicographically less than the second array; and + * a value greater than {@code 0} if the first array is + * lexicographically greater than the second array + * @since 9 + */ + public static int compareUnsigned(long[] a, long[] b) { + if (a == b) + return 0; + if (a == null || b == null) + return a == null ? -1 : 1; + + int length = Math.min(a.length, b.length); + for (int i = 0; i < length; i++) { + if (a[i] != b[i]) return Long.compareUnsigned(a[i], b[i]); + } + + return a.length - b.length; + } + + /** + * Compares two {@code long} arrays lexicographically over the specified + * ranges, numerically treating elements as unsigned. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the lexicographic comparison is the result of comparing two + * elements, as if by {@link Long#compareUnsigned(long, long)}, at a + * relative index within the respective arrays that is the length of the + * prefix. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two range lengths. + * (See {@link #mismatch(long[], int, int, long[], int, int)} for the + * definition of a common and proper prefix.) + * + * @apiNote + *

    This method behaves as if: + *

    {@code
    +     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
    +     *                             b, bFromIndex, bToIndex);
    +     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     *         return Long.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
    +     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
    +     * }
    + * + * @param a the first array to compare + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be compared + * @param aToIndex the index (exclusive) of the last element in the + * first array to be compared + * @param b the second array to compare + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be compared + * @param bToIndex the index (exclusive) of the last element in the + * second array to be compared + * @return the value {@code 0} if, over the specified ranges, the first and + * second array are equal and contain the same elements in the same + * order; + * a value less than {@code 0} if, over the specified ranges, the + * first array is lexicographically less than the second array; and + * a value greater than {@code 0} if, over the specified ranges, the + * first array is lexicographically greater than the second array + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is null + * @since 9 + */ + public static int compareUnsigned(long[] a, int aFromIndex, int aToIndex, + long[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + long va = a[aFromIndex++]; + long vb = b[bFromIndex++]; + if (va != vb) return Long.compareUnsigned(va, vb); + } + + return aLength - bLength; + } + + // Compare float + + /** + * Compares two {@code float} arrays lexicographically. + * + *

    If the two arrays share a common prefix then the lexicographic + * comparison is the result of comparing two elements, as if by + * {@link Float#compare(float, float)}, at an index within the respective + * arrays that is the prefix length. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two array lengths. + * (See {@link #mismatch(float[], float[])} for the definition of a common + * and proper prefix.) + * + *

    A {@code null} array reference is considered lexicographically less + * than a non-{@code null} array reference. Two {@code null} array + * references are considered equal. + * + *

    The comparison is consistent with {@link #equals(float[], float[]) equals}, + * more specifically the following holds for arrays {@code a} and {@code b}: + *

    {@code
    +     *     Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
    +     * }
    + * + * @apiNote + *

    This method behaves as if (for non-{@code null} array references): + *

    {@code
    +     *     int i = Arrays.mismatch(a, b);
    +     *     if (i >= 0 && i < Math.min(a.length, b.length))
    +     *         return Float.compare(a[i], b[i]);
    +     *     return a.length - b.length;
    +     * }
    + * + * @param a the first array to compare + * @param b the second array to compare + * @return the value {@code 0} if the first and second array are equal and + * contain the same elements in the same order; + * a value less than {@code 0} if the first array is + * lexicographically less than the second array; and + * a value greater than {@code 0} if the first array is + * lexicographically greater than the second array + * @since 9 + */ + public static int compare(float[] a, float[] b) { + if (a == b) + return 0; + if (a == null || b == null) + return a == null ? -1 : 1; + + int length = Math.min(a.length, b.length); + for (int i = 0; i < length; i++) { + float va = a[i], vb = b[i]; + if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb)) { + int c = Float.compare(va, vb); + if (c != 0) return c; + } + } + + return a.length - b.length; + } + + /** + * Compares two {@code float} arrays lexicographically over the specified + * ranges. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the lexicographic comparison is the result of comparing two + * elements, as if by {@link Float#compare(float, float)}, at a relative + * index within the respective arrays that is the length of the prefix. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two range lengths. + * (See {@link #mismatch(float[], int, int, float[], int, int)} for the + * definition of a common and proper prefix.) + * + *

    The comparison is consistent with + * {@link #equals(float[], int, int, float[], int, int) equals}, more + * specifically the following holds for arrays {@code a} and {@code b} with + * specified ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively: + *

    {@code
    +     *     Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
    +     *         (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
    +     * }
    + * + * @apiNote + *

    This method behaves as if: + *

    {@code
    +     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
    +     *                             b, bFromIndex, bToIndex);
    +     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     *         return Float.compare(a[aFromIndex + i], b[bFromIndex + i]);
    +     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
    +     * }
    + * + * @param a the first array to compare + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be compared + * @param aToIndex the index (exclusive) of the last element in the + * first array to be compared + * @param b the second array to compare + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be compared + * @param bToIndex the index (exclusive) of the last element in the + * second array to be compared + * @return the value {@code 0} if, over the specified ranges, the first and + * second array are equal and contain the same elements in the same + * order; + * a value less than {@code 0} if, over the specified ranges, the + * first array is lexicographically less than the second array; and + * a value greater than {@code 0} if, over the specified ranges, the + * first array is lexicographically greater than the second array + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int compare(float[] a, int aFromIndex, int aToIndex, + float[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + float va = a[aFromIndex++], vb = b[bFromIndex++]; + if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb)) { + int c = Float.compare(va, vb); + if (c != 0) return c; + } + } + + return aLength - bLength; + } + + // Compare double + + /** + * Compares two {@code double} arrays lexicographically. + * + *

    If the two arrays share a common prefix then the lexicographic + * comparison is the result of comparing two elements, as if by + * {@link Double#compare(double, double)}, at an index within the respective + * arrays that is the prefix length. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two array lengths. + * (See {@link #mismatch(double[], double[])} for the definition of a common + * and proper prefix.) + * + *

    A {@code null} array reference is considered lexicographically less + * than a non-{@code null} array reference. Two {@code null} array + * references are considered equal. + * + *

    The comparison is consistent with {@link #equals(double[], double[]) equals}, + * more specifically the following holds for arrays {@code a} and {@code b}: + *

    {@code
    +     *     Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
    +     * }
    + * + * @apiNote + *

    This method behaves as if (for non-{@code null} array references): + *

    {@code
    +     *     int i = Arrays.mismatch(a, b);
    +     *     if (i >= 0 && i < Math.min(a.length, b.length))
    +     *         return Double.compare(a[i], b[i]);
    +     *     return a.length - b.length;
    +     * }
    + * + * @param a the first array to compare + * @param b the second array to compare + * @return the value {@code 0} if the first and second array are equal and + * contain the same elements in the same order; + * a value less than {@code 0} if the first array is + * lexicographically less than the second array; and + * a value greater than {@code 0} if the first array is + * lexicographically greater than the second array + * @since 9 + */ + public static int compare(double[] a, double[] b) { + if (a == b) + return 0; + if (a == null || b == null) + return a == null ? -1 : 1; + + int length = Math.min(a.length, b.length); + for (int i = 0; i < length; i++) { + double va = a[i], vb = b[i]; + if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb)) { + int c = Double.compare(va, vb); + if (c != 0) return c; + } + } + + return a.length - b.length; + } + + /** + * Compares two {@code double} arrays lexicographically over the specified + * ranges. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the lexicographic comparison is the result of comparing two + * elements, as if by {@link Double#compare(double, double)}, at a relative + * index within the respective arrays that is the length of the prefix. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two range lengths. + * (See {@link #mismatch(double[], int, int, double[], int, int)} for the + * definition of a common and proper prefix.) + * + *

    The comparison is consistent with + * {@link #equals(double[], int, int, double[], int, int) equals}, more + * specifically the following holds for arrays {@code a} and {@code b} with + * specified ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively: + *

    {@code
    +     *     Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
    +     *         (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
    +     * }
    + * + * @apiNote + *

    This method behaves as if: + *

    {@code
    +     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
    +     *                             b, bFromIndex, bToIndex);
    +     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     *         return Double.compare(a[aFromIndex + i], b[bFromIndex + i]);
    +     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
    +     * }
    + * + * @param a the first array to compare + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be compared + * @param aToIndex the index (exclusive) of the last element in the + * first array to be compared + * @param b the second array to compare + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be compared + * @param bToIndex the index (exclusive) of the last element in the + * second array to be compared + * @return the value {@code 0} if, over the specified ranges, the first and + * second array are equal and contain the same elements in the same + * order; + * a value less than {@code 0} if, over the specified ranges, the + * first array is lexicographically less than the second array; and + * a value greater than {@code 0} if, over the specified ranges, the + * first array is lexicographically greater than the second array + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int compare(double[] a, int aFromIndex, int aToIndex, + double[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + double va = a[aFromIndex++], vb = b[bFromIndex++]; + if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb)) { + int c = Double.compare(va, vb); + if (c != 0) return c; + } + } + + return aLength - bLength; + } + + // Compare objects + + /** + * Compares two {@code Object} arrays, within comparable elements, + * lexicographically. + * + *

    If the two arrays share a common prefix then the lexicographic + * comparison is the result of comparing two elements of type {@code T} at + * an index {@code i} within the respective arrays that is the prefix + * length, as if by: + *

    {@code
    +     *     Comparator.nullsFirst(Comparator.naturalOrder()).
    +     *         compare(a[i], b[i])
    +     * }
    + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two array lengths. + * (See {@link #mismatch(Object[], Object[])} for the definition of a common + * and proper prefix.) + * + *

    A {@code null} array reference is considered lexicographically less + * than a non-{@code null} array reference. Two {@code null} array + * references are considered equal. + * A {@code null} array element is considered lexicographically than a + * non-{@code null} array element. Two {@code null} array elements are + * considered equal. + * + *

    The comparison is consistent with {@link #equals(Object[], Object[]) equals}, + * more specifically the following holds for arrays {@code a} and {@code b}: + *

    {@code
    +     *     Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
    +     * }
    + * + * @apiNote + *

    This method behaves as if (for non-{@code null} array references + * and elements): + *

    {@code
    +     *     int i = Arrays.mismatch(a, b);
    +     *     if (i >= 0 && i < Math.min(a.length, b.length))
    +     *         return a[i].compareTo(b[i]);
    +     *     return a.length - b.length;
    +     * }
    + * + * @param a the first array to compare + * @param b the second array to compare + * @param the type of comparable array elements + * @return the value {@code 0} if the first and second array are equal and + * contain the same elements in the same order; + * a value less than {@code 0} if the first array is + * lexicographically less than the second array; and + * a value greater than {@code 0} if the first array is + * lexicographically greater than the second array + * @since 9 + */ + public static > int compare(T[] a, T[] b) { + if (a == b) + return 0; + // A null array is less than a non-null array + if (a == null || b == null) + return a == null ? -1 : 1; + + int length = Math.min(a.length, b.length); + for (int i = 0; i < length; i++) { + T oa = a[i]; + T ob = b[i]; + if (oa != ob) { + // A null element is less than a non-null element + if (oa == null || ob == null) + return oa == null ? -1 : 1; + int v = oa.compareTo(ob); + if (v != 0) { + return v; + } + } + } + + return a.length - b.length; + } + + /** + * Compares two {@code Object} arrays lexicographically over the specified + * ranges. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the lexicographic comparison is the result of comparing two + * elements of type {@code T} at a relative index {@code i} within the + * respective arrays that is the prefix length, as if by: + *

    {@code
    +     *     Comparator.nullsFirst(Comparator.naturalOrder()).
    +     *         compare(a[aFromIndex + i, b[bFromIndex + i])
    +     * }
    + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two range lengths. + * (See {@link #mismatch(Object[], int, int, Object[], int, int)} for the + * definition of a common and proper prefix.) + * + *

    The comparison is consistent with + * {@link #equals(Object[], int, int, Object[], int, int) equals}, more + * specifically the following holds for arrays {@code a} and {@code b} with + * specified ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively: + *

    {@code
    +     *     Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
    +     *         (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
    +     * }
    + * + * @apiNote + *

    This method behaves as if (for non-{@code null} array elements): + *

    {@code
    +     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
    +     *                             b, bFromIndex, bToIndex);
    +     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     *         return a[aFromIndex + i].compareTo(b[bFromIndex + i]);
    +     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
    +     * }
    + * + * @param a the first array to compare + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be compared + * @param aToIndex the index (exclusive) of the last element in the + * first array to be compared + * @param b the second array to compare + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be compared + * @param bToIndex the index (exclusive) of the last element in the + * second array to be compared + * @param the type of comparable array elements + * @return the value {@code 0} if, over the specified ranges, the first and + * second array are equal and contain the same elements in the same + * order; + * a value less than {@code 0} if, over the specified ranges, the + * first array is lexicographically less than the second array; and + * a value greater than {@code 0} if, over the specified ranges, the + * first array is lexicographically greater than the second array + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static > int compare( + T[] a, int aFromIndex, int aToIndex, + T[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + T oa = a[aFromIndex++]; + T ob = b[bFromIndex++]; + if (oa != ob) { + if (oa == null || ob == null) + return oa == null ? -1 : 1; + int v = oa.compareTo(ob); + if (v != 0) { + return v; + } + } + } + + return aLength - bLength; + } + + /** + * Compares two {@code Object} arrays lexicographically using a specified + * comparator. + * + *

    If the two arrays share a common prefix then the lexicographic + * comparison is the result of comparing with the specified comparator two + * elements at an index within the respective arrays that is the prefix + * length. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two array lengths. + * (See {@link #mismatch(Object[], Object[])} for the definition of a common + * and proper prefix.) + * + *

    A {@code null} array reference is considered lexicographically less + * than a non-{@code null} array reference. Two {@code null} array + * references are considered equal. + * + * @apiNote + *

    This method behaves as if (for non-{@code null} array references): + *

    {@code
    +     *     int i = Arrays.mismatch(a, b, cmp);
    +     *     if (i >= 0 && i < Math.min(a.length, b.length))
    +     *         return cmp.compare(a[i], b[i]);
    +     *     return a.length - b.length;
    +     * }
    + * + * @param a the first array to compare + * @param b the second array to compare + * @param cmp the comparator to compare array elements + * @param the type of array elements + * @return the value {@code 0} if the first and second array are equal and + * contain the same elements in the same order; + * a value less than {@code 0} if the first array is + * lexicographically less than the second array; and + * a value greater than {@code 0} if the first array is + * lexicographically greater than the second array + * @throws NullPointerException if the comparator is {@code null} + * @since 9 + */ + public static int compare(T[] a, T[] b, + Comparator cmp) { + Objects.requireNonNull(cmp); + if (a == b) + return 0; + if (a == null || b == null) + return a == null ? -1 : 1; + + int length = Math.min(a.length, b.length); + for (int i = 0; i < length; i++) { + T oa = a[i]; + T ob = b[i]; + if (oa != ob) { + // Null-value comparison is deferred to the comparator + int v = cmp.compare(oa, ob); + if (v != 0) { + return v; + } + } + } + + return a.length - b.length; + } + + /** + * Compares two {@code Object} arrays lexicographically over the specified + * ranges. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the lexicographic comparison is the result of comparing with the + * specified comparator two elements at a relative index within the + * respective arrays that is the prefix length. + * Otherwise, one array is a proper prefix of the other and, lexicographic + * comparison is the result of comparing the two range lengths. + * (See {@link #mismatch(Object[], int, int, Object[], int, int)} for the + * definition of a common and proper prefix.) + * + * @apiNote + *

    This method behaves as if (for non-{@code null} array elements): + *

    {@code
    +     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
    +     *                             b, bFromIndex, bToIndex, cmp);
    +     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     *         return cmp.compare(a[aFromIndex + i], b[bFromIndex + i]);
    +     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
    +     * }
    + * + * @param a the first array to compare + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be compared + * @param aToIndex the index (exclusive) of the last element in the + * first array to be compared + * @param b the second array to compare + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be compared + * @param bToIndex the index (exclusive) of the last element in the + * second array to be compared + * @param cmp the comparator to compare array elements + * @param the type of array elements + * @return the value {@code 0} if, over the specified ranges, the first and + * second array are equal and contain the same elements in the same + * order; + * a value less than {@code 0} if, over the specified ranges, the + * first array is lexicographically less than the second array; and + * a value greater than {@code 0} if, over the specified ranges, the + * first array is lexicographically greater than the second array + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array or the comparator is {@code null} + * @since 9 + */ + public static int compare( + T[] a, int aFromIndex, int aToIndex, + T[] b, int bFromIndex, int bToIndex, + Comparator cmp) { + Objects.requireNonNull(cmp); + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + T oa = a[aFromIndex++]; + T ob = b[bFromIndex++]; + if (oa != ob) { + // Null-value comparison is deferred to the comparator + int v = cmp.compare(oa, ob); + if (v != 0) { + return v; + } + } + } + + return aLength - bLength; + } + + + // Mismatch methods + + // Mismatch boolean + + /** + * Finds and returns the index of the first mismatch between two + * {@code boolean} arrays, otherwise return -1 if no mismatch is found. The + * index will be in the range of 0 (inclusive) up to the length (inclusive) + * of the smaller array. + * + *

    If the two arrays share a common prefix then the returned index is the + * length of the common prefix and it follows that there is a mismatch + * between the two elements at that index within the respective arrays. + * If one array is a proper prefix of the other then the returned index is + * the length of the smaller array and it follows that the index is only + * valid for the larger array. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(a.length, b.length) &&
    +     *     Arrays.equals(a, 0, pl, b, 0, pl) &&
    +     *     a[pl] != b[pl]
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a proper + * prefix if the following expression is true: + *

    {@code
    +     *     a.length != b.length &&
    +     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
    +     *                   b, 0, Math.min(a.length, b.length))
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param b the second array to be tested for a mismatch + * @return the index of the first mismatch between the two arrays, + * otherwise {@code -1}. + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int mismatch(boolean[] a, boolean[] b) { + int length = Math.min(a.length, b.length); // Check null array refs + if (a == b) + return -1; + + for (int i = 0; i < length; i++) { + if (a[i] != b[i]) return i; + } + + return a.length != b.length ? length : -1; + } + + /** + * Finds and returns the relative index of the first mismatch between two + * {@code boolean} arrays over the specified ranges, otherwise return -1 if + * no mismatch is found. The index will be in the range of 0 (inclusive) up + * to the length (inclusive) of the smaller range. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the returned relative index is the length of the common prefix and + * it follows that there is a mismatch between the two elements at that + * relative index within the respective arrays. + * If one array is a proper prefix of the other, over the specified ranges, + * then the returned relative index is the length of the smaller range and + * it follows that the relative index is only valid for the array with the + * larger range. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
    +     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
    +     *     a[aFromIndex + pl] != b[bFromIndex + pl]
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper + * if the following expression is true: + *

    {@code
    +     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
    +     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
    +     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested for a mismatch + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @return the relative index of the first mismatch between the two arrays + * over the specified ranges, otherwise {@code -1}. + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int mismatch(boolean[] a, int aFromIndex, int aToIndex, + boolean[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + if (a[aFromIndex++] != b[bFromIndex++]) return i; + } + + return aLength != bLength ? length : -1; + } + + // Mismatch byte + + /** + * Finds and returns the index of the first mismatch between two {@code byte} + * arrays, otherwise return -1 if no mismatch is found. The index will be + * in the range of 0 (inclusive) up to the length (inclusive) of the smaller + * array. + * + *

    If the two arrays share a common prefix then the returned index is the + * length of the common prefix and it follows that there is a mismatch + * between the two elements at that index within the respective arrays. + * If one array is a proper prefix of the other then the returned index is + * the length of the smaller array and it follows that the index is only + * valid for the larger array. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(a.length, b.length) &&
    +     *     Arrays.equals(a, 0, pl, b, 0, pl) &&
    +     *     a[pl] != b[pl]
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a proper + * prefix if the following expression is true: + *

    {@code
    +     *     a.length != b.length &&
    +     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
    +     *                   b, 0, Math.min(a.length, b.length))
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param b the second array to be tested for a mismatch + * @return the index of the first mismatch between the two arrays, + * otherwise {@code -1}. + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int mismatch(byte[] a, byte[] b) { + int length = Math.min(a.length, b.length); // Check null array refs + if (a == b) + return -1; + + for (int i = 0; i < length; i++) { + if (a[i] != b[i]) return i; + } + + return a.length != b.length ? length : -1; + } + + /** + * Finds and returns the relative index of the first mismatch between two + * {@code byte} arrays over the specified ranges, otherwise return -1 if no + * mismatch is found. The index will be in the range of 0 (inclusive) up to + * the length (inclusive) of the smaller range. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the returned relative index is the length of the common prefix and + * it follows that there is a mismatch between the two elements at that + * relative index within the respective arrays. + * If one array is a proper prefix of the other, over the specified ranges, + * then the returned relative index is the length of the smaller range and + * it follows that the relative index is only valid for the array with the + * larger range. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
    +     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
    +     *     a[aFromIndex + pl] != b[bFromIndex + pl]
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper + * if the following expression is true: + *

    {@code
    +     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
    +     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
    +     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested for a mismatch + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @return the relative index of the first mismatch between the two arrays + * over the specified ranges, otherwise {@code -1}. + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int mismatch(byte[] a, int aFromIndex, int aToIndex, + byte[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + if (a[aFromIndex++] != b[bFromIndex++]) return i; + } + + return aLength != bLength ? length : -1; + } + + // Mismatch char + + /** + * Finds and returns the index of the first mismatch between two {@code char} + * arrays, otherwise return -1 if no mismatch is found. The index will be + * in the range of 0 (inclusive) up to the length (inclusive) of the smaller + * array. + * + *

    If the two arrays share a common prefix then the returned index is the + * length of the common prefix and it follows that there is a mismatch + * between the two elements at that index within the respective arrays. + * If one array is a proper prefix of the other then the returned index is + * the length of the smaller array and it follows that the index is only + * valid for the larger array. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(a.length, b.length) &&
    +     *     Arrays.equals(a, 0, pl, b, 0, pl) &&
    +     *     a[pl] != b[pl]
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a proper + * prefix if the following expression is true: + *

    {@code
    +     *     a.length != b.length &&
    +     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
    +     *                   b, 0, Math.min(a.length, b.length))
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param b the second array to be tested for a mismatch + * @return the index of the first mismatch between the two arrays, + * otherwise {@code -1}. + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int mismatch(char[] a, char[] b) { + int length = Math.min(a.length, b.length); // Check null array refs + if (a == b) + return -1; + + for (int i = 0; i < length; i++) { + if (a[i] != b[i]) return i; + } + + return a.length != b.length ? length : -1; + } + + /** + * Finds and returns the relative index of the first mismatch between two + * {@code char} arrays over the specified ranges, otherwise return -1 if no + * mismatch is found. The index will be in the range of 0 (inclusive) up to + * the length (inclusive) of the smaller range. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the returned relative index is the length of the common prefix and + * it follows that there is a mismatch between the two elements at that + * relative index within the respective arrays. + * If one array is a proper prefix of the other, over the specified ranges, + * then the returned relative index is the length of the smaller range and + * it follows that the relative index is only valid for the array with the + * larger range. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
    +     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
    +     *     a[aFromIndex + pl] != b[bFromIndex + pl]
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper + * if the following expression is true: + *

    {@code
    +     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
    +     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
    +     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested for a mismatch + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @return the relative index of the first mismatch between the two arrays + * over the specified ranges, otherwise {@code -1}. + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int mismatch(char[] a, int aFromIndex, int aToIndex, + char[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + if (a[aFromIndex++] != b[bFromIndex++]) return i; + } + + return aLength != bLength ? length : -1; + } + + // Mismatch short + + /** + * Finds and returns the index of the first mismatch between two {@code short} + * arrays, otherwise return -1 if no mismatch is found. The index will be + * in the range of 0 (inclusive) up to the length (inclusive) of the smaller + * array. + * + *

    If the two arrays share a common prefix then the returned index is the + * length of the common prefix and it follows that there is a mismatch + * between the two elements at that index within the respective arrays. + * If one array is a proper prefix of the other then the returned index is + * the length of the smaller array and it follows that the index is only + * valid for the larger array. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(a.length, b.length) &&
    +     *     Arrays.equals(a, 0, pl, b, 0, pl) &&
    +     *     a[pl] != b[pl]
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a proper + * prefix if the following expression is true: + *

    {@code
    +     *     a.length != b.length &&
    +     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
    +     *                   b, 0, Math.min(a.length, b.length))
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param b the second array to be tested for a mismatch + * @return the index of the first mismatch between the two arrays, + * otherwise {@code -1}. + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int mismatch(short[] a, short[] b) { + int length = Math.min(a.length, b.length); // Check null array refs + if (a == b) + return -1; + + for (int i = 0; i < length; i++) { + if (a[i] != b[i]) return i; + } + + return a.length != b.length ? length : -1; + } + + /** + * Finds and returns the relative index of the first mismatch between two + * {@code short} arrays over the specified ranges, otherwise return -1 if no + * mismatch is found. The index will be in the range of 0 (inclusive) up to + * the length (inclusive) of the smaller range. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the returned relative index is the length of the common prefix and + * it follows that there is a mismatch between the two elements at that + * relative index within the respective arrays. + * If one array is a proper prefix of the other, over the specified ranges, + * then the returned relative index is the length of the smaller range and + * it follows that the relative index is only valid for the array with the + * larger range. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
    +     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
    +     *     a[aFromIndex + pl] != b[bFromIndex + pl]
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper + * if the following expression is true: + *

    {@code
    +     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
    +     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
    +     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested for a mismatch + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @return the relative index of the first mismatch between the two arrays + * over the specified ranges, otherwise {@code -1}. + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int mismatch(short[] a, int aFromIndex, int aToIndex, + short[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + if (a[aFromIndex++] != b[bFromIndex++]) return i; + } + + return aLength != bLength ? length : -1; + } + + // Mismatch int + + /** + * Finds and returns the index of the first mismatch between two {@code int} + * arrays, otherwise return -1 if no mismatch is found. The index will be + * in the range of 0 (inclusive) up to the length (inclusive) of the smaller + * array. + * + *

    If the two arrays share a common prefix then the returned index is the + * length of the common prefix and it follows that there is a mismatch + * between the two elements at that index within the respective arrays. + * If one array is a proper prefix of the other then the returned index is + * the length of the smaller array and it follows that the index is only + * valid for the larger array. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(a.length, b.length) &&
    +     *     Arrays.equals(a, 0, pl, b, 0, pl) &&
    +     *     a[pl] != b[pl]
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a proper + * prefix if the following expression is true: + *

    {@code
    +     *     a.length != b.length &&
    +     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
    +     *                   b, 0, Math.min(a.length, b.length))
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param b the second array to be tested for a mismatch + * @return the index of the first mismatch between the two arrays, + * otherwise {@code -1}. + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int mismatch(int[] a, int[] b) { + int length = Math.min(a.length, b.length); // Check null array refs + if (a == b) + return -1; + + for (int i = 0; i < length; i++) { + if (a[i] != b[i]) return i; + } + + return a.length != b.length ? length : -1; + } + + /** + * Finds and returns the relative index of the first mismatch between two + * {@code int} arrays over the specified ranges, otherwise return -1 if no + * mismatch is found. The index will be in the range of 0 (inclusive) up to + * the length (inclusive) of the smaller range. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the returned relative index is the length of the common prefix and + * it follows that there is a mismatch between the two elements at that + * relative index within the respective arrays. + * If one array is a proper prefix of the other, over the specified ranges, + * then the returned relative index is the length of the smaller range and + * it follows that the relative index is only valid for the array with the + * larger range. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
    +     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
    +     *     a[aFromIndex + pl] != b[bFromIndex + pl]
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper + * if the following expression is true: + *

    {@code
    +     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
    +     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
    +     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested for a mismatch + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @return the relative index of the first mismatch between the two arrays + * over the specified ranges, otherwise {@code -1}. + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int mismatch(int[] a, int aFromIndex, int aToIndex, + int[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + if (a[aFromIndex++] != b[bFromIndex++]) return i; + } + + return aLength != bLength ? length : -1; + } + + // Mismatch long + + /** + * Finds and returns the index of the first mismatch between two {@code long} + * arrays, otherwise return -1 if no mismatch is found. The index will be + * in the range of 0 (inclusive) up to the length (inclusive) of the smaller + * array. + * + *

    If the two arrays share a common prefix then the returned index is the + * length of the common prefix and it follows that there is a mismatch + * between the two elements at that index within the respective arrays. + * If one array is a proper prefix of the other then the returned index is + * the length of the smaller array and it follows that the index is only + * valid for the larger array. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(a.length, b.length) &&
    +     *     Arrays.equals(a, 0, pl, b, 0, pl) &&
    +     *     a[pl] != b[pl]
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a proper + * prefix if the following expression is true: + *

    {@code
    +     *     a.length != b.length &&
    +     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
    +     *                   b, 0, Math.min(a.length, b.length))
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param b the second array to be tested for a mismatch + * @return the index of the first mismatch between the two arrays, + * otherwise {@code -1}. + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int mismatch(long[] a, long[] b) { + int length = Math.min(a.length, b.length); // Check null array refs + if (a == b) + return -1; + + for (int i = 0; i < length; i++) { + if (a[i] != b[i]) return i; + } + + return a.length != b.length ? length : -1; + } + + /** + * Finds and returns the relative index of the first mismatch between two + * {@code long} arrays over the specified ranges, otherwise return -1 if no + * mismatch is found. The index will be in the range of 0 (inclusive) up to + * the length (inclusive) of the smaller range. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the returned relative index is the length of the common prefix and + * it follows that there is a mismatch between the two elements at that + * relative index within the respective arrays. + * If one array is a proper prefix of the other, over the specified ranges, + * then the returned relative index is the length of the smaller range and + * it follows that the relative index is only valid for the array with the + * larger range. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
    +     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
    +     *     a[aFromIndex + pl] != b[bFromIndex + pl]
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper + * if the following expression is true: + *

    {@code
    +     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
    +     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
    +     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested for a mismatch + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @return the relative index of the first mismatch between the two arrays + * over the specified ranges, otherwise {@code -1}. + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int mismatch(long[] a, int aFromIndex, int aToIndex, + long[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + if (a[aFromIndex++] != b[bFromIndex++]) return i; + } + + return aLength != bLength ? length : -1; + } + + // Mismatch float + + /** + * Finds and returns the index of the first mismatch between two {@code float} + * arrays, otherwise return -1 if no mismatch is found. The index will be + * in the range of 0 (inclusive) up to the length (inclusive) of the smaller + * array. + * + *

    If the two arrays share a common prefix then the returned index is the + * length of the common prefix and it follows that there is a mismatch + * between the two elements at that index within the respective arrays. + * If one array is a proper prefix of the other then the returned index is + * the length of the smaller array and it follows that the index is only + * valid for the larger array. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(a.length, b.length) &&
    +     *     Arrays.equals(a, 0, pl, b, 0, pl) &&
    +     *     Float.compare(a[pl], b[pl]) != 0
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a proper + * prefix if the following expression is true: + *

    {@code
    +     *     a.length != b.length &&
    +     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
    +     *                   b, 0, Math.min(a.length, b.length))
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param b the second array to be tested for a mismatch + * @return the index of the first mismatch between the two arrays, + * otherwise {@code -1}. + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int mismatch(float[] a, float[] b) { + int length = Math.min(a.length, b.length); // Check null array refs + if (a == b) + return -1; + + for (int i = 0; i < length; i++) { + float va = a[i], vb = b[i]; + if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb)) + if (!Float.isNaN(va) || !Float.isNaN(vb)) + return i; + } + + return a.length != b.length ? length : -1; + } + + /** + * Finds and returns the relative index of the first mismatch between two + * {@code float} arrays over the specified ranges, otherwise return -1 if no + * mismatch is found. The index will be in the range of 0 (inclusive) up to + * the length (inclusive) of the smaller range. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the returned relative index is the length of the common prefix and + * it follows that there is a mismatch between the two elements at that + * relative index within the respective arrays. + * If one array is a proper prefix of the other, over the specified ranges, + * then the returned relative index is the length of the smaller range and + * it follows that the relative index is only valid for the array with the + * larger range. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
    +     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
    +     *     Float.compare(a[aFromIndex + pl], b[bFromIndex + pl]) != 0
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper + * if the following expression is true: + *

    {@code
    +     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
    +     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
    +     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested for a mismatch + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @return the relative index of the first mismatch between the two arrays + * over the specified ranges, otherwise {@code -1}. + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int mismatch(float[] a, int aFromIndex, int aToIndex, + float[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + float va = a[aFromIndex++], vb = b[bFromIndex++]; + if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb)) + if (!Float.isNaN(va) || !Float.isNaN(vb)) + return i; + } + + return aLength != bLength ? length : -1; + } + + // Mismatch double + + /** + * Finds and returns the index of the first mismatch between two + * {@code double} arrays, otherwise return -1 if no mismatch is found. The + * index will be in the range of 0 (inclusive) up to the length (inclusive) + * of the smaller array. + * + *

    If the two arrays share a common prefix then the returned index is the + * length of the common prefix and it follows that there is a mismatch + * between the two elements at that index within the respective arrays. + * If one array is a proper prefix of the other then the returned index is + * the length of the smaller array and it follows that the index is only + * valid for the larger array. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(a.length, b.length) &&
    +     *     Arrays.equals(a, 0, pl, b, 0, pl) &&
    +     *     Double.compare(a[pl], b[pl]) != 0
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a proper + * prefix if the following expression is true: + *

    {@code
    +     *     a.length != b.length &&
    +     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
    +     *                   b, 0, Math.min(a.length, b.length))
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param b the second array to be tested for a mismatch + * @return the index of the first mismatch between the two arrays, + * otherwise {@code -1}. + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int mismatch(double[] a, double[] b) { + int length = Math.min(a.length, b.length); // Check null array refs + if (a == b) + return -1; + + for (int i = 0; i < length; i++) { + double va = a[i], vb = b[i]; + if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb)) + if (!Double.isNaN(va) || !Double.isNaN(vb)) + return i; + } + + return a.length != b.length ? length : -1; + } + + /** + * Finds and returns the relative index of the first mismatch between two + * {@code double} arrays over the specified ranges, otherwise return -1 if + * no mismatch is found. The index will be in the range of 0 (inclusive) up + * to the length (inclusive) of the smaller range. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the returned relative index is the length of the common prefix and + * it follows that there is a mismatch between the two elements at that + * relative index within the respective arrays. + * If one array is a proper prefix of the other, over the specified ranges, + * then the returned relative index is the length of the smaller range and + * it follows that the relative index is only valid for the array with the + * larger range. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
    +     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
    +     *     Double.compare(a[aFromIndex + pl], b[bFromIndex + pl]) != 0
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper + * if the following expression is true: + *

    {@code
    +     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
    +     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
    +     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested for a mismatch + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @return the relative index of the first mismatch between the two arrays + * over the specified ranges, otherwise {@code -1}. + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int mismatch(double[] a, int aFromIndex, int aToIndex, + double[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + double va = a[aFromIndex++], vb = b[bFromIndex++]; + if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb)) + if (!Double.isNaN(va) || !Double.isNaN(vb)) + return i; + } + + return aLength != bLength ? length : -1; + } + + // Mismatch objects + + /** + * Finds and returns the index of the first mismatch between two + * {@code Object} arrays, otherwise return -1 if no mismatch is found. The + * index will be in the range of 0 (inclusive) up to the length (inclusive) + * of the smaller array. + * + *

    If the two arrays share a common prefix then the returned index is the + * length of the common prefix and it follows that there is a mismatch + * between the two elements at that index within the respective arrays. + * If one array is a proper prefix of the other then the returned index is + * the length of the smaller array and it follows that the index is only + * valid for the larger array. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(a.length, b.length) &&
    +     *     Arrays.equals(a, 0, pl, b, 0, pl) &&
    +     *     !Objects.equals(a[pl], b[pl])
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a proper + * prefix if the following expression is true: + *

    {@code
    +     *     a.length != b.length &&
    +     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
    +     *                   b, 0, Math.min(a.length, b.length))
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param b the second array to be tested for a mismatch + * @return the index of the first mismatch between the two arrays, + * otherwise {@code -1}. + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int mismatch(Object[] a, Object[] b) { + int length = Math.min(a.length, b.length); // Check null array refs + if (a == b) + return -1; + + for (int i = 0; i < length; i++) { + if (!Objects.equals(a[i], b[i])) + return i; + } + + return a.length != b.length ? length : -1; + } + + /** + * Finds and returns the relative index of the first mismatch between two + * {@code Object} arrays over the specified ranges, otherwise return -1 if + * no mismatch is found. The index will be in the range of 0 (inclusive) up + * to the length (inclusive) of the smaller range. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the returned relative index is the length of the common prefix and + * it follows that there is a mismatch between the two elements at that + * relative index within the respective arrays. + * If one array is a proper prefix of the other, over the specified ranges, + * then the returned relative index is the length of the smaller range and + * it follows that the relative index is only valid for the array with the + * larger range. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
    +     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
    +     *     !Objects.equals(a[aFromIndex + pl], b[bFromIndex + pl])
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper + * if the following expression is true: + *

    {@code
    +     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
    +     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
    +     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested for a mismatch + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @return the relative index of the first mismatch between the two arrays + * over the specified ranges, otherwise {@code -1}. + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array is {@code null} + * @since 9 + */ + public static int mismatch( + Object[] a, int aFromIndex, int aToIndex, + Object[] b, int bFromIndex, int bToIndex) { + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + if (!Objects.equals(a[aFromIndex++], b[bFromIndex++])) + return i; + } + + return aLength != bLength ? length : -1; + } + + /** + * Finds and returns the index of the first mismatch between two + * {@code Object} arrays, otherwise return -1 if no mismatch is found. + * The index will be in the range of 0 (inclusive) up to the length + * (inclusive) of the smaller array. + * + *

    The specified comparator is used to determine if two array elements + * from the each array are not equal. + * + *

    If the two arrays share a common prefix then the returned index is the + * length of the common prefix and it follows that there is a mismatch + * between the two elements at that index within the respective arrays. + * If one array is a proper prefix of the other then the returned index is + * the length of the smaller array and it follows that the index is only + * valid for the larger array. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(a.length, b.length) &&
    +     *     IntStream.range(0, pl).
    +     *         map(i -> cmp.compare(a[i], b[i])).
    +     *         allMatch(c -> c == 0) &&
    +     *     cmp.compare(a[pl], b[pl]) != 0
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b}, share a proper + * prefix if the following expression is true: + *

    {@code
    +     *     a.length != b.length &&
    +     *     IntStream.range(0, Math.min(a.length, b.length)).
    +     *         map(i -> cmp.compare(a[i], b[i])).
    +     *         allMatch(c -> c == 0) &&
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param b the second array to be tested for a mismatch + * @param cmp the comparator to compare array elements + * @param the type of array elements + * @return the index of the first mismatch between the two arrays, + * otherwise {@code -1}. + * @throws NullPointerException + * if either array or the comparator is {@code null} + * @since 9 + */ + public static int mismatch(T[] a, T[] b, Comparator cmp) { + Objects.requireNonNull(cmp); + int length = Math.min(a.length, b.length); // Check null array refs + if (a == b) + return -1; + + for (int i = 0; i < length; i++) { + T oa = a[i]; + T ob = b[i]; + if (oa != ob) { + // Null-value comparison is deferred to the comparator + int v = cmp.compare(oa, ob); + if (v != 0) { + return i; + } + } + } + + return a.length != b.length ? length : -1; + } + + /** + * Finds and returns the relative index of the first mismatch between two + * {@code Object} arrays over the specified ranges, otherwise return -1 if + * no mismatch is found. The index will be in the range of 0 (inclusive) up + * to the length (inclusive) of the smaller range. + * + *

    If the two arrays, over the specified ranges, share a common prefix + * then the returned relative index is the length of the common prefix and + * it follows that there is a mismatch between the two elements at that + * relative index within the respective arrays. + * If one array is a proper prefix of the other, over the specified ranges, + * then the returned relative index is the length of the smaller range and + * it follows that the relative index is only valid for the array with the + * larger range. + * Otherwise, there is no mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common + * prefix of length {@code pl} if the following expression is true: + *

    {@code
    +     *     pl >= 0 &&
    +     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
    +     *     IntStream.range(0, pl).
    +     *         map(i -> cmp.compare(a[aFromIndex + i], b[bFromIndex + i])).
    +     *         allMatch(c -> c == 0) &&
    +     *     cmp.compare(a[aFromIndex + pl], b[bFromIndex + pl]) != 0
    +     * }
    + * Note that a common prefix length of {@code 0} indicates that the first + * elements from each array mismatch. + * + *

    Two non-{@code null} arrays, {@code a} and {@code b} with specified + * ranges [{@code aFromIndex}, {@code atoIndex}) and + * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper + * if the following expression is true: + *

    {@code
    +     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
    +     *     IntStream.range(0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex)).
    +     *         map(i -> cmp.compare(a[aFromIndex + i], b[bFromIndex + i])).
    +     *         allMatch(c -> c == 0)
    +     * }
    + * + * @param a the first array to be tested for a mismatch + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested for a mismatch + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @param cmp the comparator to compare array elements + * @param the type of array elements + * @return the relative index of the first mismatch between the two arrays + * over the specified ranges, otherwise {@code -1}. + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array or the comparator is {@code null} + * @since 9 + */ + public static int mismatch( + T[] a, int aFromIndex, int aToIndex, + T[] b, int bFromIndex, int bToIndex, + Comparator cmp) { + Objects.requireNonNull(cmp); + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + int length = Math.min(aLength, bLength); + for (int i = 0; i < length; i++) { + T oa = a[aFromIndex++]; + T ob = b[bFromIndex++]; + if (oa != ob) { + // Null-value comparison is deferred to the comparator + int v = cmp.compare(oa, ob); + if (v != 0) { + return i; + } + } + } + + return aLength != bLength ? length : -1; + } +} \ No newline at end of file diff --git a/jdk/test/java/util/Arrays/ArraysEqCmpTest.java b/jdk/test/java/util/Arrays/ArraysEqCmpTest.java new file mode 100644 index 00000000000..590b71668b4 --- /dev/null +++ b/jdk/test/java/util/Arrays/ArraysEqCmpTest.java @@ -0,0 +1,1083 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8033148 + * @summary tests for array equals and compare + * @run testng ArraysEqCmpTest +*/ + +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.BiFunction; +import java.util.function.LongFunction; +import java.util.stream.IntStream; + +public class ArraysEqCmpTest { + + // Maximum width in bits + static final int MAX_WIDTH = 512; + + static final Map typeToWidth; + + static { + typeToWidth = new HashMap<>(); + typeToWidth.put(boolean.class, Byte.SIZE); + typeToWidth.put(byte.class, Byte.SIZE); + typeToWidth.put(short.class, Short.SIZE); + typeToWidth.put(char.class, Character.SIZE); + typeToWidth.put(int.class, Integer.SIZE); + typeToWidth.put(long.class, Long.SIZE); + typeToWidth.put(float.class, Float.SIZE); + typeToWidth.put(double.class, Double.SIZE); + typeToWidth.put(Object.class, Integer.SIZE); // @@@ 32 or 64? + } + + static int arraySizeFor(Class type) { + type = type.isPrimitive() ? type : Object.class; + return 4 * MAX_WIDTH / typeToWidth.get(type); + } + + static abstract class ArrayType { + final Class arrayType; + final Class componentType; + final boolean unsigned; + + final MethodHandle cpy; + + final MethodHandle eq; + final MethodHandle eqr; + final MethodHandle cmp; + final MethodHandle cmpr; + final MethodHandle mm; + final MethodHandle mmr; + + final MethodHandle getter; + + final MethodHandle toString; + + public ArrayType(Class arrayType) { + this(arrayType, false); + } + + public ArrayType(Class arrayType, boolean unsigned) { + this.arrayType = arrayType; + this.componentType = arrayType.getComponentType(); + this.unsigned = unsigned; + + try { + MethodHandles.Lookup l = MethodHandles.lookup(); + + getter = MethodHandles.arrayElementGetter(arrayType); + + if (componentType.isPrimitive()) { + cpy = l.findStatic(Arrays.class, "copyOfRange", + MethodType.methodType(arrayType, arrayType, int.class, int.class)); + + MethodType eqt = MethodType.methodType( + boolean.class, arrayType, arrayType); + MethodType eqrt = MethodType.methodType( + boolean.class, arrayType, int.class, int.class, arrayType, int.class, int.class); + + eq = l.findStatic(Arrays.class, "equals", eqt); + eqr = l.findStatic(Arrays.class, "equals", eqrt); + + String compareName = unsigned ? "compareUnsigned" : "compare"; + cmp = l.findStatic(Arrays.class, compareName, + eqt.changeReturnType(int.class)); + cmpr = l.findStatic(Arrays.class, compareName, + eqrt.changeReturnType(int.class)); + + mm = l.findStatic(Arrays.class, "mismatch", + eqt.changeReturnType(int.class)); + mmr = l.findStatic(Arrays.class, "mismatch", + eqrt.changeReturnType(int.class)); + + toString = l.findStatic(Arrays.class, "toString", + MethodType.methodType(String.class, arrayType)); + } + else { + cpy = l.findStatic(Arrays.class, "copyOfRange", + MethodType.methodType(Object[].class, Object[].class, int.class, int.class)); + + MethodType eqt = MethodType.methodType( + boolean.class, Object[].class, Object[].class); + MethodType eqrt = MethodType.methodType( + boolean.class, Object[].class, int.class, int.class, Object[].class, int.class, int.class); + + eq = l.findStatic(Arrays.class, "equals", eqt); + eqr = l.findStatic(Arrays.class, "equals", eqrt); + + MethodType cmpt = MethodType.methodType( + int.class, Comparable[].class, Comparable[].class); + MethodType cmprt = MethodType.methodType( + int.class, Comparable[].class, int.class, int.class, Comparable[].class, int.class, int.class); + + cmp = l.findStatic(Arrays.class, "compare", cmpt); + cmpr = l.findStatic(Arrays.class, "compare", cmprt); + + mm = l.findStatic(Arrays.class, "mismatch", + eqt.changeReturnType(int.class)); + mmr = l.findStatic(Arrays.class, "mismatch", + eqrt.changeReturnType(int.class)); + + toString = l.findStatic(Arrays.class, "toString", + MethodType.methodType(String.class, Object[].class)); + } + + } + catch (Exception e) { + throw new Error(e); + } + } + + @Override + public String toString() { + String s = arrayType.getCanonicalName(); + return unsigned ? "unsigned " + s : s; + } + + Object construct(int length) { + return Array.newInstance(componentType, length); + } + + Object copyOf(Object a) { + return copyOf(a, 0, Array.getLength(a)); + } + + Object copyOf(Object a, int from, int to) { + try { + return (Object) cpy.invoke(a, from, to); + } + catch (RuntimeException | Error e) { + throw e; + } + catch (Throwable t) { + throw new Error(t); + } + } + + Object get(Object a, int i) { + try { + return (Object) getter.invoke(a, i); + } + catch (RuntimeException | Error e) { + throw e; + } + catch (Throwable t) { + throw new Error(t); + } + } + + abstract void set(Object a, int i, Object v); + + boolean equals(Object a, Object b) { + try { + return (boolean) eq.invoke(a, b); + } + catch (RuntimeException | Error e) { + throw e; + } + catch (Throwable t) { + throw new Error(t); + } + } + + boolean equals(Object a, int aFromIndex, int aToIndex, + Object b, int bFromIndex, int bToIndex) { + try { + return (boolean) eqr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex); + } + catch (RuntimeException | Error e) { + throw e; + } + catch (Throwable t) { + throw new Error(t); + } + } + + int compare(Object a, Object b) { + try { + return (int) cmp.invoke(a, b); + } + catch (RuntimeException | Error e) { + throw e; + } + catch (Throwable t) { + throw new Error(t); + } + } + + int compare(Object a, int aFromIndex, int aToIndex, + Object b, int bFromIndex, int bToIndex) { + try { + return (int) cmpr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex); + } + catch (RuntimeException | Error e) { + throw e; + } + catch (Throwable t) { + throw new Error(t); + } + } + + int mismatch(Object a, Object b) { + try { + return (int) mm.invoke(a, b); + } + catch (RuntimeException | Error e) { + throw e; + } + catch (Throwable t) { + throw new Error(t); + } + } + + int mismatch(Object a, int aFromIndex, int aToIndex, + Object b, int bFromIndex, int bToIndex) { + try { + return (int) mmr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex); + } + catch (RuntimeException | Error e) { + throw e; + } + catch (Throwable t) { + throw new Error(t); + } + } + + String toString(Object a) { + try { + return (String) toString.invoke(a); + } + catch (RuntimeException | Error e) { + throw e; + } + catch (Throwable t) { + throw new Error(t); + } + } + + static class BoxedIntegers extends ArrayType { + public BoxedIntegers() { + super(Integer[].class); + } + + @Override + void set(Object a, int i, Object v) { + // Ensure unique reference + ((Integer[]) a)[i] = v != null ? new Integer((Integer) v) : null; + } + } + + static class BoxedIntegersWithReverseComparator extends BoxedIntegers { + final Comparator c = (a, b) -> { + // Nulls sort after non-nulls + if (a == null || b == null) + return a == null ? b == null ? 0 : 1 : -1; + + return Integer.compare(b, a); + }; + + final MethodHandle cmpc; + final MethodHandle cmpcr; + final MethodHandle mismatchc; + final MethodHandle mismatchcr; + + public BoxedIntegersWithReverseComparator() { + try { + MethodHandles.Lookup l = MethodHandles.lookup(); + + MethodType cmpt = MethodType.methodType( + int.class, Object[].class, Object[].class, Comparator.class); + MethodType cmprt = MethodType.methodType( + int.class, Object[].class, int.class, int.class, + Object[].class, int.class, int.class, Comparator.class); + + cmpc = l.findStatic(Arrays.class, "compare", cmpt); + cmpcr = l.findStatic(Arrays.class, "compare", cmprt); + mismatchc = l.findStatic(Arrays.class, "mismatch", cmpt); + mismatchcr = l.findStatic(Arrays.class, "mismatch", cmprt); + } + catch (Exception e) { + throw new Error(e); + } + } + + @Override + int compare(Object a, Object b) { + try { + return (int) cmpc.invoke(a, b, c); + } + catch (RuntimeException | Error e) { + throw e; + } + catch (Throwable t) { + throw new Error(t); + } + } + + @Override + int compare(Object a, int aFromIndex, int aToIndex, + Object b, int bFromIndex, int bToIndex) { + try { + return (int) cmpcr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex, c); + } + catch (RuntimeException | Error e) { + throw e; + } + catch (Throwable t) { + throw new Error(t); + } + } + + @Override + int mismatch(Object a, Object b) { + try { + return (int) mismatchc.invoke(a, b, c); + } + catch (RuntimeException | Error e) { + throw e; + } + catch (Throwable t) { + throw new Error(t); + } + } + + @Override + int mismatch(Object a, int aFromIndex, int aToIndex, + Object b, int bFromIndex, int bToIndex) { + try { + return (int) mismatchcr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex, c); + } + catch (RuntimeException | Error e) { + throw e; + } + catch (Throwable t) { + throw new Error(t); + } + } + + @Override + public String toString() { + return arrayType.getCanonicalName() + " with Comparator"; + } + } + + static class Booleans extends ArrayType { + public Booleans() { + super(boolean[].class); + } + + @Override + void set(Object a, int i, Object v) { + boolean pv; + if (v instanceof Boolean) { + pv = (Boolean) v; + } + else if (v instanceof Integer) { + pv = ((Integer) v) >= 0; + } + else throw new IllegalStateException(); + + ((boolean[]) a)[i] = pv; + } + } + + static class Bytes extends ArrayType { + public Bytes(boolean unsigned) { + super(byte[].class, unsigned); + } + + @Override + void set(Object a, int i, Object v) { + byte pv; + if (v instanceof Byte) { + pv = (Byte) v; + } + else if (v instanceof Integer) { + pv = ((Integer) v).byteValue(); + } + else throw new IllegalStateException(); + + ((byte[]) a)[i] = pv; + } + } + + static class Characters extends ArrayType { + public Characters() { + super(char[].class); + } + + @Override + void set(Object a, int i, Object v) { + char pv; + if (v instanceof Character) { + pv = (Character) v; + } + else if (v instanceof Integer) { + pv = (char) ((Integer) v).intValue(); + } + else throw new IllegalStateException(); + + ((char[]) a)[i] = pv; + } + } + + static class Shorts extends ArrayType { + public Shorts(boolean unsigned) { + super(short[].class, unsigned); + } + + @Override + void set(Object a, int i, Object v) { + short pv; + if (v instanceof Short) { + pv = (Short) v; + } + else if (v instanceof Integer) { + pv = ((Integer) v).shortValue(); + } + else throw new IllegalStateException(); + + ((short[]) a)[i] = pv; + } + } + + static class Integers extends ArrayType { + public Integers(boolean unsigned) { + super(int[].class, unsigned); + } + + @Override + void set(Object a, int i, Object v) { + int pv; + if (v instanceof Integer) { + pv = ((Integer) v).shortValue(); + } + else throw new IllegalStateException(); + + ((int[]) a)[i] = pv; + } + } + + static class Longs extends ArrayType { + public Longs(boolean unsigned) { + super(long[].class, unsigned); + } + + @Override + void set(Object a, int i, Object v) { + long pv; + if (v instanceof Long) { + pv = (Long) v; + } + else if (v instanceof Integer) { + pv = ((Integer) v).longValue(); + } + else throw new IllegalStateException(); + + ((long[]) a)[i] = pv; + } + } + + static class Floats extends ArrayType { + public Floats() { + super(float[].class); + } + + @Override + void set(Object a, int i, Object v) { + float pv; + if (v instanceof Float) { + pv = (Float) v; + } + else if (v instanceof Integer) { + pv = ((Integer) v).floatValue(); + } + else throw new IllegalStateException(); + + ((float[]) a)[i] = pv; + } + } + + static class Doubles extends ArrayType { + public Doubles() { + super(double[].class); + } + + @Override + void set(Object a, int i, Object v) { + double pv; + if (v instanceof Double) { + pv = (Double) v; + } + else if (v instanceof Integer) { + pv = ((Integer) v).doubleValue(); + } + else throw new IllegalStateException(); + + ((double[]) a)[i] = pv; + } + } + } + + static Object[][] arrayTypes; + + @DataProvider + public static Object[][] arrayTypesProvider() { + if (arrayTypes == null) { + arrayTypes = new Object[][]{ + new Object[]{new ArrayType.BoxedIntegers()}, + new Object[]{new ArrayType.BoxedIntegersWithReverseComparator()}, + new Object[]{new ArrayType.Booleans()}, + new Object[]{new ArrayType.Bytes(false)}, + new Object[]{new ArrayType.Bytes(true)}, + new Object[]{new ArrayType.Characters()}, + new Object[]{new ArrayType.Shorts(false)}, + new Object[]{new ArrayType.Shorts(true)}, + new Object[]{new ArrayType.Integers(false)}, + new Object[]{new ArrayType.Integers(true)}, + new Object[]{new ArrayType.Longs(false)}, + new Object[]{new ArrayType.Longs(true)}, + new Object[]{new ArrayType.Floats()}, + new Object[]{new ArrayType.Doubles()}, + }; + } + return arrayTypes; + } + + static Object[][] floatArrayTypes; + + @DataProvider + public static Object[][] floatArrayTypesProvider() { + if (floatArrayTypes == null) { + LongFunction bTof = rb -> Float.intBitsToFloat((int) rb); + LongFunction bToD = Double::longBitsToDouble; + + floatArrayTypes = new Object[][]{ + new Object[]{new ArrayType.Floats(), 0x7fc00000L, 0x7f800001L, bTof}, + new Object[]{new ArrayType.Doubles(), 0x7ff8000000000000L, 0x7ff0000000000001L, bToD}, + }; + } + return floatArrayTypes; + } + + static Object[][] objectArrayTypes; + + @DataProvider + public static Object[][] objectArrayTypesProvider() { + if (objectArrayTypes == null) { + LongFunction bTof = rb -> Float.intBitsToFloat((int) rb); + LongFunction bToD = Double::longBitsToDouble; + + objectArrayTypes = new Object[][]{ + new Object[]{new ArrayType.BoxedIntegers()}, + new Object[]{new ArrayType.BoxedIntegersWithReverseComparator()}, + }; + } + return objectArrayTypes; + } + + + static Object[][] signedUnsignedArrayTypes; + + @DataProvider + public static Object[][] signedUnsignedArrayTypes() { + if (signedUnsignedArrayTypes == null) { + signedUnsignedArrayTypes = new Object[][]{ + new Object[]{new ArrayType.Bytes(false), new ArrayType.Bytes(true)}, + new Object[]{new ArrayType.Shorts(false), new ArrayType.Shorts(true)}, + new Object[]{new ArrayType.Integers(false), new ArrayType.Integers(true)}, + new Object[]{new ArrayType.Longs(false), new ArrayType.Longs(true)}, + }; + } + return signedUnsignedArrayTypes; + } + + // Equality and comparison tests + + @Test(dataProvider = "arrayTypesProvider") + public void testArray(ArrayType arrayType) { + BiFunction, Integer, Object> constructor = (at, s) -> { + Object a = at.construct(s); + for (int x = 0; x < s; x++) { + at.set(a, x, x % 8); + } + return a; + }; + + BiFunction, Object, Object> cloner = (at, a) -> + constructor.apply(at, Array.getLength(a)); + + testArrayType(arrayType, constructor, cloner); + } + + @Test(dataProvider = "floatArrayTypesProvider") + public void testPrimitiveFloatArray( + ArrayType arrayType, + long canonicalNanRawBits, long nonCanonicalNanRawBits, + LongFunction bitsToFloat) { + Object canonicalNan = bitsToFloat.apply(canonicalNanRawBits); + // If conversion is a signalling NaN it may be subject to conversion to a + // quiet NaN on some processors, even if a copy is performed + // The tests assume that if conversion occurs it does not convert to the + // canonical NaN + Object nonCanonicalNan = bitsToFloat.apply(nonCanonicalNanRawBits); + + BiFunction, Integer, Object> canonicalNaNs = (at, s) -> { + Object a = at.construct(s); + for (int x = 0; x < s; x++) { + at.set(a, x, canonicalNan); + } + return a; + }; + + BiFunction, Object, Object> nonCanonicalNaNs = (at, a) -> { + int s = Array.getLength(a); + Object ac = at.construct(s); + for (int x = 0; x < s; x++) { + at.set(ac, x, nonCanonicalNan); + } + return ac; + }; + + BiFunction, Object, Object> halfNonCanonicalNaNs = (at, a) -> { + int s = Array.getLength(a); + Object ac = at.construct(s); + for (int x = 0; x < s / 2; x++) { + at.set(ac, x, nonCanonicalNan); + } + for (int x = s / 2; x < s; x++) { + at.set(ac, x, 1); + } + return ac; + }; + + testArrayType(arrayType, canonicalNaNs, nonCanonicalNaNs); + testArrayType(arrayType, canonicalNaNs, halfNonCanonicalNaNs); + } + + @Test(dataProvider = "objectArrayTypesProvider") + public void testNullElementsInObjectArray(ArrayType arrayType) { + BiFunction, Object, Object> cloner = ArrayType::copyOf; + + // All nulls + testArrayType(arrayType, + (at, s) -> { + Object a = at.construct(s); + for (int x = 0; x < s; x++) { + at.set(a, x, null); + } + return a; + }, + cloner); + + + // Some nulls + testArrayType(arrayType, + (at, s) -> { + Object a = at.construct(s); + for (int x = 0; x < s; x++) { + int v = x % 8; + at.set(a, x, v == 0 ? null : v); + } + return a; + }, + cloner); + + Integer[] a = new Integer[]{null, 0}; + Integer[] b = new Integer[]{0, 0}; + Assert.assertTrue(Arrays.compare(a, b) < 0); + Assert.assertTrue(Arrays.compare(b, a) > 0); + } + + @Test(dataProvider = "objectArrayTypesProvider") + public void testSameRefElementsInObjectArray(ArrayType arrayType) { + BiFunction, Object, Object> cloner = ArrayType::copyOf; + + // One ref + Integer one = 1; + testArrayType(arrayType, + (at, s) -> { + Integer[] a = (Integer[]) at.construct(s); + for (int x = 0; x < s; x++) { + a[x] = one; + } + return a; + }, + cloner); + + // All ref + testArrayType(arrayType, + (at, s) -> { + Integer[] a = (Integer[]) at.construct(s); + for (int x = 0; x < s; x++) { + a[x] = Integer.valueOf(s); + } + return a; + }, + cloner); + + // Some same ref + testArrayType(arrayType, + (at, s) -> { + Integer[] a = (Integer[]) at.construct(s); + for (int x = 0; x < s; x++) { + int v = x % 8; + a[x] = v == 1 ? one : new Integer(v); + } + return a; + }, + cloner); + } + + @Test(dataProvider = "signedUnsignedArrayTypes") + public void testSignedUnsignedArray(ArrayType sat, ArrayType uat) { + BiFunction, Integer, Object> constructor = (at, s) -> { + Object a = at.construct(s); + for (int x = 0; x < s; x++) { + at.set(a, x, 1); + } + return a; + }; + + int n = arraySizeFor(sat.componentType); + + for (int s : ranges(0, n)) { + Object a = constructor.apply(sat, s); + + for (int aFrom : ranges(0, s)) { + for (int aTo : ranges(aFrom, s)) { + int aLength = aTo - aFrom; + + if (aLength > 0) { + for (int i = aFrom; i < aTo; i++) { + Object ac = sat.copyOf(a); + // Create common prefix with a length of i - aFrom + sat.set(ac, i, -1); + + int sc = sat.compare(ac, aFrom, aTo, a, aFrom, aTo); + int uc = uat.compare(ac, aFrom, aTo, a, aFrom, aTo); + + Assert.assertTrue(sc < 0); + Assert.assertTrue(uc > 0); + } + } + } + } + } + } + + void testArrayType(ArrayType at, + BiFunction, Integer, Object> constructor, + BiFunction, Object, Object> cloner) { + int n = arraySizeFor(at.componentType); + + for (int s : ranges(0, n)) { + Object a = constructor.apply(at, s); + Object b = cloner.apply(at, a); + + for (int aFrom : ranges(0, s)) { + for (int aTo : ranges(aFrom, s)) { + int aLength = aTo - aFrom; + + for (int bFrom : ranges(0, s)) { + for (int bTo : ranges(bFrom, s)) { + int bLength = bTo - bFrom; + + Object anr = at.copyOf(a, aFrom, aTo); + Object bnr = at.copyOf(b, bFrom, bTo); + + boolean eq = isEqual(at, a, aFrom, aTo, b, bFrom, bTo); + Assert.assertEquals(at.equals(a, aFrom, aTo, b, bFrom, bTo), eq); + Assert.assertEquals(at.equals(b, bFrom, bTo, a, aFrom, aTo), eq); + Assert.assertEquals(at.equals(anr, bnr), eq); + Assert.assertEquals(at.equals(bnr, anr), eq); + if (eq) { + Assert.assertEquals(at.compare(a, aFrom, aTo, b, bFrom, bTo), 0); + Assert.assertEquals(at.compare(b, bFrom, bTo, a, aFrom, aTo), 0); + Assert.assertEquals(at.compare(anr, bnr), 0); + Assert.assertEquals(at.compare(bnr, anr), 0); + + Assert.assertEquals(at.mismatch(a, aFrom, aTo, b, bFrom, bTo), -1); + Assert.assertEquals(at.mismatch(b, bFrom, bTo, a, aFrom, aTo), -1); + Assert.assertEquals(at.mismatch(anr, bnr), -1); + Assert.assertEquals(at.mismatch(bnr, anr), -1); + } + else { + int aCb = at.compare(a, aFrom, aTo, b, bFrom, bTo); + int bCa = at.compare(b, bFrom, bTo, a, aFrom, aTo); + int v = Integer.signum(aCb) * Integer.signum(bCa); + Assert.assertTrue(v == -1); + + int anrCbnr = at.compare(anr, bnr); + int bnrCanr = at.compare(bnr, anr); + Assert.assertEquals(anrCbnr, aCb); + Assert.assertEquals(bnrCanr, bCa); + + + int aMb = at.mismatch(a, aFrom, aTo, b, bFrom, bTo); + int bMa = at.mismatch(b, bFrom, bTo, a, aFrom, aTo); + int anrMbnr = at.mismatch(anr, bnr); + int bnrManr = at.mismatch(bnr, anr); + + Assert.assertNotEquals(aMb, -1); + Assert.assertEquals(aMb, bMa); + Assert.assertNotEquals(anrMbnr, -1); + Assert.assertEquals(anrMbnr, bnrManr); + Assert.assertEquals(aMb, anrMbnr); + Assert.assertEquals(bMa, bnrManr); + + // Common or proper prefix + Assert.assertTrue(at.equals(a, aFrom, aFrom + aMb, b, bFrom, bFrom + aMb)); + if (aMb < Math.min(aLength, bLength)) { + // Common prefix + Assert.assertFalse(isEqual(at, a, aFrom + aMb, b, bFrom + aMb)); + } + } + } + } + + if (aLength > 0) { + for (int i = aFrom; i < aTo; i++) { + Object ac = at.copyOf(a); + // Create common prefix with a length of i - aFrom + at.set(ac, i, -1); + + Object acnr = at.copyOf(ac, aFrom, aTo); + Object anr = at.copyOf(a, aFrom, aTo); + + Assert.assertFalse(at.equals(ac, aFrom, aTo, a, aFrom, aTo)); + Assert.assertFalse(at.equals(acnr, anr)); + + int acCa = at.compare(ac, aFrom, aTo, a, aFrom, aTo); + int aCac = at.compare(a, aFrom, aTo, ac, aFrom, aTo); + int v = Integer.signum(acCa) * Integer.signum(aCac); + Assert.assertTrue(v == -1); + + int acnrCanr = at.compare(acnr, anr); + int anrCacnr = at.compare(anr, acnr); + Assert.assertEquals(acnrCanr, acCa); + Assert.assertEquals(anrCacnr, aCac); + + + int acMa = at.mismatch(ac, aFrom, aTo, a, aFrom, aTo); + int aMac = at.mismatch(a, aFrom, aTo, ac, aFrom, aTo); + Assert.assertEquals(acMa, aMac); + Assert.assertEquals(acMa, i - aFrom); + + int acnrManr = at.mismatch(acnr, anr); + int anrMacnr = at.mismatch(anr, acnr); + Assert.assertEquals(acnrManr, anrMacnr); + Assert.assertEquals(acnrManr, i - aFrom); + } + } + } + } + } + } + + static boolean isEqual(ArrayType at, Object a, int aFromIndex, int aToIndex, + Object b, int bFromIndex, int bToIndex) { + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + if (aLength != bLength) + return false; + + for (int i = 0; i < aLength; i++) { + Object av = at.get(a, aFromIndex++); + Object bv = at.get(b, bFromIndex++); + if (!Objects.equals(av, bv)) return false; + } + + return true; + } + + static boolean isEqual(ArrayType at, Object a, int aFrom, Object b, int bFrom) { + Object av = at.get(a, aFrom); + Object bv = at.get(b, bFrom); + + return Objects.equals(av, bv); + } + + static int[] ranges(int from, int to) { + int width = to - from; + switch (width) { + case 0: + return new int[]{}; + case 1: + return new int[]{from, to}; + case 2: + return new int[]{from, from + 1, to}; + case 3: + return new int[]{from, from + 1, from + 2, to}; + default: + return IntStream.of(from, from + 1, from + 2, to / 2 - 1, to / 2, to / 2 + 1, to - 2, to - 1, to) + .filter(i -> i >= from && i <= to) + .distinct().toArray(); + } + } + + + // Null array reference tests + + @Test(dataProvider = "arrayTypesProvider") + public void testNullArrayRefs(ArrayType arrayType) { + Object n = null; + Object a = arrayType.construct(0); + + Assert.assertTrue(arrayType.equals(n, n)); + Assert.assertFalse(arrayType.equals(n, a)); + Assert.assertFalse(arrayType.equals(a, n)); + + Assert.assertEquals(arrayType.compare(n, n), 0); + Assert.assertTrue(arrayType.compare(n, a) < 0); + Assert.assertTrue(arrayType.compare(a, n) > 0); + } + + + // Exception throwing tests + + @Test(dataProvider = "arrayTypesProvider") + public void testNPEs(ArrayType arrayType) { + Object[] values = new Object[]{null, arrayType.construct(0)}; + + for (Object o1 : values) { + for (Object o2 : values) { + if (o1 != null && o2 != null) + continue; + + testNPE(() -> arrayType.equals(o1, 0, 0, o2, 0, 0)); + testNPE(() -> arrayType.compare(o1, 0, 0, o2, 0, 0)); + testNPE(() -> arrayType.mismatch(o1, o2)); + testNPE(() -> arrayType.mismatch(o1, 0, 0, o2, 0, 0)); + } + } + } + + @Test + public void testObjectNPEs() { + String[][] values = new String[][]{null, new String[0]}; + Comparator c = String::compareTo; + Comparator[] cs = new Comparator[]{null, c}; + + for (String[] o1 : values) { + for (String[] o2 : values) { + for (Comparator o3 : cs) { + if (o1 != null && o2 != null && o3 != null) + continue; + + if (o3 == null) { + testNPE(() -> Arrays.compare(o1, o2, o3)); + testNPE(() -> Arrays.mismatch(o1, o2, o3)); + } + + testNPE(() -> Arrays.compare(o1, 0, 0, o2, 0, 0, o3)); + testNPE(() -> Arrays.mismatch(o1, 0, 0, o2, 0, 0, o3)); + } + } + } + } + + @Test(dataProvider = "arrayTypesProvider") + public void testIAEs(ArrayType arrayType) { + List values = Arrays.asList(0, 1); + + for (int s : values) { + Object a = arrayType.construct(s); + + for (int o1 : values) { + for (int o2 : values) { + if (o1 <= o2) continue; + + testIAE(() -> arrayType.equals(a, o1, 0, a, o2, 0)); + testIAE(() -> arrayType.compare(a, o1, 0, a, o2, 0)); + testIAE(() -> arrayType.mismatch(a, o1, 0, a, o2, 0)); + } + } + } + } + + @Test(dataProvider = "arrayTypesProvider") + public void testAIOBEs(ArrayType arrayType) { + List froms = Arrays.asList(-1, 0); + + for (int s : Arrays.asList(0, 1)) { + List tos = Arrays.asList(s, s + 1); + Object a = arrayType.construct(s); + + for (int aFrom : froms) { + for (int aTo : tos) { + for (int bFrom : froms) { + for (int bTo : tos) { + if (aFrom >= 0 && aTo <= s && + bFrom >= 0 && bTo <= s) continue; + + testAIOBE(() -> arrayType.equals(a, aFrom, aTo, a, bFrom, bTo)); + testAIOBE(() -> arrayType.compare(a, aFrom, aTo, a, bFrom, bTo)); + testAIOBE(() -> arrayType.mismatch(a, aFrom, aTo, a, bFrom, bTo)); + } + } + } + } + } + } + + static void testNPE(Runnable r) { + testThrowable(r, NullPointerException.class); + } + + static void testIAE(Runnable r) { + testThrowable(r, IllegalArgumentException.class); + } + + static void testAIOBE(Runnable r) { + testThrowable(r, ArrayIndexOutOfBoundsException.class); + } + + static void testThrowable(Runnable r, Class expected) { + Throwable caught = null; + try { + r.run(); + } + catch (Throwable t) { + caught = t; + } + Assert.assertNotNull(caught); + Assert.assertTrue(expected.isInstance(caught)); + } +} \ No newline at end of file From afaeebc08d7e122186407b1fec00a3e73e9dae14 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Wed, 4 Nov 2015 09:01:15 -0800 Subject: [PATCH 24/31] 8141359: @Deprecated on packages should be clarified Reviewed-by: rriggs --- jdk/src/java.base/share/classes/java/lang/Deprecated.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/java.base/share/classes/java/lang/Deprecated.java b/jdk/src/java.base/share/classes/java/lang/Deprecated.java index 7adc22edaf5..f9c177b38c4 100644 --- a/jdk/src/java.base/share/classes/java/lang/Deprecated.java +++ b/jdk/src/java.base/share/classes/java/lang/Deprecated.java @@ -36,7 +36,7 @@ import static java.lang.annotation.ElementType.*; * *

    Use of the @Deprecated annotation on a local variable * declaration or on a parameter declaration or a package declaration - * has no effect. + * has no effect on the warnings issued by a compiler. * * @author Neal Gafter * @since 1.5 From 12381786ed765e40684bf5ba84e434eba7076615 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Wed, 4 Nov 2015 11:27:58 -0800 Subject: [PATCH 25/31] 8141454: Move java/lang/ProcessHandle/TreeTest.java until stability improves Reviewed-by: rriggs --- jdk/test/TEST.groups | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jdk/test/TEST.groups b/jdk/test/TEST.groups index b2f73a7cd9f..72fc5e9dd06 100644 --- a/jdk/test/TEST.groups +++ b/jdk/test/TEST.groups @@ -27,6 +27,7 @@ tier1 = \ :jdk_lang \ + -java/lang/ProcessHandle/TreeTest.java \ :jdk_util \ sun/nio/cs/ISO8859x.java \ java/nio/Buffer \ @@ -34,6 +35,7 @@ tier1 = \ :jdk_math tier2 = \ + java/lang/ProcessHandle/TreeTest.java \ :jdk_io \ :jdk_nio \ -sun/nio/cs/ISO8859x.java \ From a74cf79db439c07fd93eadba56e324c10c8a84cf Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 4 Nov 2015 14:06:45 -0800 Subject: [PATCH 26/31] 8140630: java/nio/Buffer/Basic.java crashes vm on linux-x64 using latest devkit to build Build Bits.c at a lower optimization level on linux-x64. Reviewed-by: tbell --- jdk/make/lib/CoreLibraries.gmk | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk index 99f5f752204..01ae7467e5d 100644 --- a/jdk/make/lib/CoreLibraries.gmk +++ b/jdk/make/lib/CoreLibraries.gmk @@ -139,6 +139,12 @@ ifeq ($(OPENJDK_TARGET_OS), solaris) endif endif +ifeq ($(OPENJDK_TARGET_OS), linux) + ifeq ($(OPENJDK_TARGET_CPU), x86_64) + BUILD_LIBJAVA_Bits.c_CFLAGS := $(C_O_FLAG_NORM) + endif +endif + $(eval $(call SetupNativeCompilation,BUILD_LIBJAVA, \ LIBRARY := java, \ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ From 5aee1308cad99a689eb3bbc8a2c0566437313139 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Thu, 5 Nov 2015 10:54:05 +0100 Subject: [PATCH 27/31] 8141444: Clean up building of JDK launchers Reviewed-by: erikj --- jdk/make/launcher/Launcher-java.base.gmk | 41 ++-- jdk/make/launcher/Launcher-java.corba.gmk | 39 ++-- jdk/make/launcher/Launcher-java.desktop.gmk | 10 +- jdk/make/launcher/Launcher-java.rmi.gmk | 12 +- jdk/make/launcher/Launcher-java.scripting.gmk | 8 +- .../launcher/Launcher-java.security.jgss.gmk | 18 +- jdk/make/launcher/Launcher-jdk.compiler.gmk | 38 ++-- jdk/make/launcher/Launcher-jdk.dev.gmk | 7 +- .../launcher/Launcher-jdk.hotspot.agent.gmk | 17 +- jdk/make/launcher/Launcher-jdk.jartool.gmk | 10 +- jdk/make/launcher/Launcher-jdk.javadoc.gmk | 12 +- jdk/make/launcher/Launcher-jdk.jcmd.gmk | 63 +++--- jdk/make/launcher/Launcher-jdk.jconsole.gmk | 13 +- jdk/make/launcher/Launcher-jdk.jdeps.gmk | 18 +- jdk/make/launcher/Launcher-jdk.jdi.gmk | 10 +- jdk/make/launcher/Launcher-jdk.jshell.gmk | 9 +- jdk/make/launcher/Launcher-jdk.jvmstat.gmk | 8 +- jdk/make/launcher/Launcher-jdk.pack200.gmk | 7 +- jdk/make/launcher/Launcher-jdk.policytool.gmk | 9 +- jdk/make/launcher/Launcher-jdk.rmic.gmk | 10 +- .../Launcher-jdk.scripting.nashorn.shell.gmk | 10 +- jdk/make/launcher/Launcher-jdk.xml.bind.gmk | 13 +- jdk/make/launcher/Launcher-jdk.xml.ws.gmk | 13 +- jdk/make/launcher/LauncherCommon.gmk | 186 +++++++++--------- 24 files changed, 311 insertions(+), 270 deletions(-) diff --git a/jdk/make/launcher/Launcher-java.base.gmk b/jdk/make/launcher/Launcher-java.base.gmk index 1cbab01bcad..abe829ad4d3 100644 --- a/jdk/make/launcher/Launcher-java.base.gmk +++ b/jdk/make/launcher/Launcher-java.base.gmk @@ -25,32 +25,51 @@ include LauncherCommon.gmk +JAVA_RC_FLAGS += -i $(JDK_TOPDIR)/src/java.base/windows/native/common +ifdef OPENJDK + JAVA_RC_FLAGS += -i "$(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons" +else + JAVA_RC_FLAGS += -i "$(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons" +endif + ################################################################################ # On windows, the debuginfo files get the same name as for java.dll. Build # into another dir and copy selectively so debuginfo for java.dll isn't # overwritten. -$(eval $(call SetupLauncher,java, \ - -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES,,,user32.lib comctl32.lib, \ - $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jli_static.lib, $(JAVA_RC_FLAGS), \ - $(JAVA_VERSION_INFO_RESOURCE), $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/java_objs,true)) +$(eval $(call SetupBuildLauncher, java, \ + CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES, \ + LDFLAGS_solaris := -R$(OPENWIN_HOME)/lib$(OPENJDK_TARGET_CPU_ISADIR), \ + LIBS_windows := user32.lib comctl32.lib, \ + RC_FLAGS := $(JAVA_RC_FLAGS), \ + VERSION_INFO_RESOURCE := $(JAVA_VERSION_INFO_RESOURCE), \ + OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/java_objs, \ + OPTIMIZATION := HIGH, \ + WINDOWS_STATIC_LINK := true, \ + NO_JAVA_MS := true, \ +)) $(SUPPORT_OUTPUTDIR)/modules_cmds/java.base/java$(EXE_SUFFIX): $(BUILD_LAUNCHER_java) $(MKDIR) -p $(@D) $(RM) $@ - $(CP) $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/java_objs$(OUTPUT_SUBDIR)/java$(EXE_SUFFIX) $@ + $(CP) $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/java_objs/java$(EXE_SUFFIX) $@ TARGETS += $(SUPPORT_OUTPUTDIR)/modules_cmds/java.base/java$(EXE_SUFFIX) ifeq ($(OPENJDK_TARGET_OS), windows) - $(eval $(call SetupLauncher,javaw, \ - -DJAVAW -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES,,,user32.lib comctl32.lib, \ - $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jli_static.lib, $(JAVA_RC_FLAGS), \ - $(JAVA_VERSION_INFO_RESOURCE),,true)) + $(eval $(call SetupBuildLauncher, javaw, \ + CFLAGS := -DJAVAW -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES, \ + LIBS_windows := user32.lib comctl32.lib, \ + RC_FLAGS := $(JAVA_RC_FLAGS), \ + VERSION_INFO_RESOURCE := $(JAVA_VERSION_INFO_RESOURCE), \ + WINDOWS_STATIC_LINK := true, \ + NO_JAVA_MS := true, \ + )) endif -$(eval $(call SetupLauncher,keytool, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.security.tools.keytool.Main"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, keytool, \ + MAIN_CLASS := sun.security.tools.keytool.Main, \ +)) ################################################################################ diff --git a/jdk/make/launcher/Launcher-java.corba.gmk b/jdk/make/launcher/Launcher-java.corba.gmk index 8404c556bcb..f859877bbc2 100644 --- a/jdk/make/launcher/Launcher-java.corba.gmk +++ b/jdk/make/launcher/Launcher-java.corba.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,23 +25,26 @@ include LauncherCommon.gmk -$(eval $(call SetupLauncher,idlj, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.corba.se.idl.toJavaPortable.Compile"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, idlj, \ + MAIN_CLASS := com.sun.tools.corba.se.idl.toJavaPortable.Compile, \ +)) -$(eval $(call SetupLauncher,orbd, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) \ - "-J-Dcom.sun.CORBA.activation.DbDir=./orb.db"$(COMMA) \ - "-J-Dcom.sun.CORBA.activation.Port=1049"$(COMMA) \ - "-J-Dcom.sun.CORBA.POA.ORBServerId=1"$(COMMA) \ - "com.sun.corba.se.impl.activation.ORBD"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, orbd, \ + MAIN_CLASS := com.sun.corba.se.impl.activation.ORBD, \ + JAVA_ARGS := \ + -Dcom.sun.CORBA.activation.DbDir=./orb.db \ + -Dcom.sun.CORBA.activation.Port=1049 \ + -Dcom.sun.CORBA.POA.ORBServerId=1, \ +)) -$(eval $(call SetupLauncher,servertool, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.corba.se.impl.activation.ServerTool"$(COMMA) }')) - -$(eval $(call SetupLauncher,tnameserv, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) \ - "-J-Dcom.sun.CORBA.activation.DbDir=./orb.db"$(COMMA) \ - "-J-Djava.util.logging.LoggingPermission=contol"$(COMMA) \ - "-J-Dcom.sun.CORBA.POA.ORBServerId=1"$(COMMA) \ - "com.sun.corba.se.impl.naming.cosnaming.TransientNameServer"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, servertool, \ + MAIN_CLASS := com.sun.corba.se.impl.activation.ServerTool, \ +)) +$(eval $(call SetupBuildLauncher, tnameserv, \ + MAIN_CLASS := com.sun.corba.se.impl.naming.cosnaming.TransientNameServer, \ + JAVA_ARGS := \ + -Dcom.sun.CORBA.activation.DbDir=./orb.db \ + -Djava.util.logging.LoggingPermission=contol \ + -Dcom.sun.CORBA.POA.ORBServerId=1, \ +)) diff --git a/jdk/make/launcher/Launcher-java.desktop.gmk b/jdk/make/launcher/Launcher-java.desktop.gmk index 1b36c691a03..2bb3c4923f2 100644 --- a/jdk/make/launcher/Launcher-java.desktop.gmk +++ b/jdk/make/launcher/Launcher-java.desktop.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -29,8 +29,8 @@ include LauncherCommon.gmk $(eval $(call IncludeCustomExtension, jdk, launcher/Launcher-java.desktop.gmk)) ifndef BUILD_HEADLESS_ONLY - $(eval $(call SetupLauncher,appletviewer, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.applet.Main"$(COMMA) }',, \ - $(XLIBS))) + $(eval $(call SetupBuildLauncher, appletviewer, \ + MAIN_CLASS := sun.applet.Main, \ + LIBS_unix := $(X_LIBS), \ + )) endif - diff --git a/jdk/make/launcher/Launcher-java.rmi.gmk b/jdk/make/launcher/Launcher-java.rmi.gmk index 58b2328713e..a69a90bcc81 100644 --- a/jdk/make/launcher/Launcher-java.rmi.gmk +++ b/jdk/make/launcher/Launcher-java.rmi.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,10 @@ include LauncherCommon.gmk -$(eval $(call SetupLauncher,rmid, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.rmi.server.Activation"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, rmid, \ + MAIN_CLASS := sun.rmi.server.Activation, \ +)) -$(eval $(call SetupLauncher,rmiregistry, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.rmi.registry.RegistryImpl"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, rmiregistry, \ + MAIN_CLASS := sun.rmi.registry.RegistryImpl, \ +)) diff --git a/jdk/make/launcher/Launcher-java.scripting.gmk b/jdk/make/launcher/Launcher-java.scripting.gmk index 14889a7f77b..bf8f97084ec 100644 --- a/jdk/make/launcher/Launcher-java.scripting.gmk +++ b/jdk/make/launcher/Launcher-java.scripting.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,6 @@ include LauncherCommon.gmk -$(eval $(call SetupLauncher,jrunscript, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.script.shell.Main"$(COMMA) }')) - +$(eval $(call SetupBuildLauncher, jrunscript, \ + MAIN_CLASS := com.sun.tools.script.shell.Main, \ +)) diff --git a/jdk/make/launcher/Launcher-java.security.jgss.gmk b/jdk/make/launcher/Launcher-java.security.jgss.gmk index 818503ed569..7411e1a21c4 100644 --- a/jdk/make/launcher/Launcher-java.security.jgss.gmk +++ b/jdk/make/launcher/Launcher-java.security.jgss.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -26,13 +26,15 @@ include LauncherCommon.gmk ifeq ($(OPENJDK_TARGET_OS), windows) - $(eval $(call SetupLauncher,kinit, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.security.krb5.internal.tools.Kinit"$(COMMA) }')) + $(eval $(call SetupBuildLauncher, kinit, \ + MAIN_CLASS := sun.security.krb5.internal.tools.Kinit, \ + )) - $(eval $(call SetupLauncher,klist, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.security.krb5.internal.tools.Klist"$(COMMA) }')) + $(eval $(call SetupBuildLauncher, klist, \ + MAIN_CLASS := sun.security.krb5.internal.tools.Klist, \ + )) - $(eval $(call SetupLauncher,ktab, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.security.krb5.internal.tools.Ktab"$(COMMA) }')) + $(eval $(call SetupBuildLauncher, ktab, \ + MAIN_CLASS := sun.security.krb5.internal.tools.Ktab, \ + )) endif - diff --git a/jdk/make/launcher/Launcher-jdk.compiler.gmk b/jdk/make/launcher/Launcher-jdk.compiler.gmk index 8025085e49e..d1947dae9f2 100644 --- a/jdk/make/launcher/Launcher-jdk.compiler.gmk +++ b/jdk/make/launcher/Launcher-jdk.compiler.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,26 +25,30 @@ include LauncherCommon.gmk -$(eval $(call SetupLauncher,javac, \ - -DEXPAND_CLASSPATH_WILDCARDS \ - -DNEVER_ACT_AS_SERVER_CLASS_MACHINE \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.javac.Main"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, javac, \ + MAIN_CLASS := com.sun.tools.javac.Main, \ + CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \ + -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \ +)) -$(eval $(call SetupLauncher,javah, \ - -DEXPAND_CLASSPATH_WILDCARDS \ - -DNEVER_ACT_AS_SERVER_CLASS_MACHINE \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.javah.Main"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, javah, \ + MAIN_CLASS := com.sun.tools.javah.Main, \ + CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \ + -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \ +)) -$(eval $(call SetupLauncher,serialver, \ - -DEXPAND_CLASSPATH_WILDCARDS \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.tools.serialver.SerialVer"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, serialver, \ + MAIN_CLASS := sun.tools.serialver.SerialVer, \ + CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ +)) ifeq ($(ENABLE_SJAVAC), yes) # Build sjavac directly to the exploded image so that it does not get included # into any real images - $(eval $(call SetupLauncher,sjavac, \ - -DEXPAND_CLASSPATH_WILDCARDS \ - -DNEVER_ACT_AS_SERVER_CLASS_MACHINE \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.sjavac.Main"$(COMMA) }',,,,,,, \ - $(JDK_OUTPUTDIR)/bin)) + $(eval $(call SetupBuildLauncher, sjavac, \ + MAIN_CLASS := com.sun.tools.sjavac.Main, \ + CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \ + -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \ + OUTPUT_DIR := $(JDK_OUTPUTDIR)/bin, \ + )) endif diff --git a/jdk/make/launcher/Launcher-jdk.dev.gmk b/jdk/make/launcher/Launcher-jdk.dev.gmk index 61cfffb29f2..d874ae9372c 100644 --- a/jdk/make/launcher/Launcher-jdk.dev.gmk +++ b/jdk/make/launcher/Launcher-jdk.dev.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,5 +25,6 @@ include LauncherCommon.gmk -$(eval $(call SetupLauncher,jimage,\ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "jdk.tools.jimage.Main"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, jimage,\ + MAIN_CLASS := jdk.tools.jimage.Main, \ +)) diff --git a/jdk/make/launcher/Launcher-jdk.hotspot.agent.gmk b/jdk/make/launcher/Launcher-jdk.hotspot.agent.gmk index ce1e3309d94..9acc6ea5884 100644 --- a/jdk/make/launcher/Launcher-jdk.hotspot.agent.gmk +++ b/jdk/make/launcher/Launcher-jdk.hotspot.agent.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,13 @@ include LauncherCommon.gmk -$(eval $(call SetupLauncher,jsadebugd, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.jvm.hotspot.jdi.SADebugServer"$(COMMA) }' \ - ,,,,,,,,,Info-privileged.plist)) +$(eval $(call SetupBuildLauncher, jsadebugd, \ + MAIN_CLASS := sun.jvm.hotspot.jdi.SADebugServer, \ + MACOSX_SIGNED := true, \ +)) -$(eval $(call SetupLauncher,jhsdb, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.jvm.hotspot.SALauncher"$(COMMA) }' \ - ,,,,,,,,,Info-privileged.plist)) - +$(eval $(call SetupBuildLauncher, jhsdb, \ + MAIN_CLASS := sun.jvm.hotspot.SALauncher, \ + MACOSX_SIGNED := true, \ +)) diff --git a/jdk/make/launcher/Launcher-jdk.jartool.gmk b/jdk/make/launcher/Launcher-jdk.jartool.gmk index b6d44e315ff..f74e82bfdae 100644 --- a/jdk/make/launcher/Launcher-jdk.jartool.gmk +++ b/jdk/make/launcher/Launcher-jdk.jartool.gmk @@ -25,8 +25,10 @@ include LauncherCommon.gmk -$(eval $(call SetupLauncher,jar, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.tools.jar.Main"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, jar, \ + MAIN_CLASS := sun.tools.jar.Main, \ +)) -$(eval $(call SetupLauncher,jarsigner, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.security.tools.jarsigner.Main"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, jarsigner, \ + MAIN_CLASS := sun.security.tools.jarsigner.Main, \ +)) diff --git a/jdk/make/launcher/Launcher-jdk.javadoc.gmk b/jdk/make/launcher/Launcher-jdk.javadoc.gmk index 65eac4f120c..5922c40d8da 100644 --- a/jdk/make/launcher/Launcher-jdk.javadoc.gmk +++ b/jdk/make/launcher/Launcher-jdk.javadoc.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,8 @@ include LauncherCommon.gmk -$(eval $(call SetupLauncher,javadoc, \ - -DEXPAND_CLASSPATH_WILDCARDS \ - -DNEVER_ACT_AS_SERVER_CLASS_MACHINE \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.javadoc.Main"$(COMMA) }')) - +$(eval $(call SetupBuildLauncher, javadoc, \ + MAIN_CLASS := com.sun.tools.javadoc.Main, \ + CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \ + -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \ +)) diff --git a/jdk/make/launcher/Launcher-jdk.jcmd.gmk b/jdk/make/launcher/Launcher-jdk.jcmd.gmk index 9e3f7ceb13e..34d24418550 100644 --- a/jdk/make/launcher/Launcher-jdk.jcmd.gmk +++ b/jdk/make/launcher/Launcher-jdk.jcmd.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,36 +25,41 @@ include LauncherCommon.gmk -$(eval $(call SetupLauncher,jinfo, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) \ - "-J-Dsun.jvm.hotspot.debugger.useProcDebugger"$(COMMA) \ - "-J-Dsun.jvm.hotspot.debugger.useWindbgDebugger"$(COMMA) \ - "sun.tools.jinfo.JInfo"$(COMMA) }' \ - -DAPP_CLASSPATH='{ "/lib/tools.jar"$(COMMA) "/lib/sa-jdi.jar"$(COMMA) "/classes" }' \ - ,,,,,,,,,Info-privileged.plist)) +$(eval $(call SetupBuildLauncher, jinfo, \ + MAIN_CLASS := sun.tools.jinfo.JInfo, \ + JAVA_ARGS := \ + -Dsun.jvm.hotspot.debugger.useProcDebugger \ + -Dsun.jvm.hotspot.debugger.useWindbgDebugger, \ + APP_CLASSPATH := /lib/tools.jar /lib/sa-jdi.jar /classes, \ + MACOSX_SIGNED := true, \ +)) -$(eval $(call SetupLauncher,jmap, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) \ - "-J-Dsun.jvm.hotspot.debugger.useProcDebugger"$(COMMA) \ - "-J-Dsun.jvm.hotspot.debugger.useWindbgDebugger"$(COMMA) \ - "sun.tools.jmap.JMap"$(COMMA) }' \ - -DAPP_CLASSPATH='{ "/lib/tools.jar"$(COMMA) "/lib/sa-jdi.jar"$(COMMA) "/classes" }' \ - ,,,,,,,,,Info-privileged.plist)) +$(eval $(call SetupBuildLauncher, jmap, \ + MAIN_CLASS := sun.tools.jmap.JMap, \ + JAVA_ARGS := \ + -Dsun.jvm.hotspot.debugger.useProcDebugger \ + -Dsun.jvm.hotspot.debugger.useWindbgDebugger, \ + APP_CLASSPATH := /lib/tools.jar /lib/sa-jdi.jar /classes, \ + MACOSX_SIGNED := true, \ +)) -$(eval $(call SetupLauncher,jps, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.tools.jps.Jps"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, jps, \ + MAIN_CLASS := sun.tools.jps.Jps, \ +)) -$(eval $(call SetupLauncher,jstack, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) \ - "-J-Dsun.jvm.hotspot.debugger.useProcDebugger"$(COMMA) \ - "-J-Dsun.jvm.hotspot.debugger.useWindbgDebugger"$(COMMA) \ - "sun.tools.jstack.JStack"$(COMMA) }' \ - -DAPP_CLASSPATH='{ "/lib/tools.jar"$(COMMA) "/lib/sa-jdi.jar"$(COMMA) "/classes" }' \ - ,,,,,,,,,Info-privileged.plist)) +$(eval $(call SetupBuildLauncher, jstack, \ + MAIN_CLASS := sun.tools.jstack.JStack, \ + JAVA_ARGS := \ + -Dsun.jvm.hotspot.debugger.useProcDebugger \ + -Dsun.jvm.hotspot.debugger.useWindbgDebugger, \ + APP_CLASSPATH := /lib/tools.jar /lib/sa-jdi.jar /classes, \ + MACOSX_SIGNED := true, \ +)) -$(eval $(call SetupLauncher,jstat, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.tools.jstat.Jstat"$(COMMA) }')) - -$(eval $(call SetupLauncher,jcmd, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.tools.jcmd.JCmd"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, jstat, \ + MAIN_CLASS := sun.tools.jstat.Jstat, \ +)) +$(eval $(call SetupBuildLauncher, jcmd, \ + MAIN_CLASS := sun.tools.jcmd.JCmd, \ +)) diff --git a/jdk/make/launcher/Launcher-jdk.jconsole.gmk b/jdk/make/launcher/Launcher-jdk.jconsole.gmk index 905117cb53b..7c5ada82382 100644 --- a/jdk/make/launcher/Launcher-jdk.jconsole.gmk +++ b/jdk/make/launcher/Launcher-jdk.jconsole.gmk @@ -25,9 +25,10 @@ include LauncherCommon.gmk -BUILD_LAUNCHER_jconsole_CFLAGS_windows := -DJAVAW -BUILD_LAUNCHER_jconsole_LIBS_windows := user32.lib - -$(eval $(call SetupLauncher,jconsole, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "-J-Djconsole.showOutputViewer"$(COMMA) "sun.tools.jconsole.JConsole"$(COMMA) }' \ - -DAPP_CLASSPATH='{ "/lib/jconsole.jar"$(COMMA) "/lib/tools.jar"$(COMMA) "/classes" }')) +$(eval $(call SetupBuildLauncher, jconsole, \ + MAIN_CLASS := sun.tools.jconsole.JConsole, \ + JAVA_ARGS := -Djconsole.showOutputViewer, \ + APP_CLASSPATH := /lib/jconsole.jar /lib/tools.jar /classes, \ + CFLAGS_windows := -DJAVAW, \ + LIBS_windows := user32.lib, \ +)) diff --git a/jdk/make/launcher/Launcher-jdk.jdeps.gmk b/jdk/make/launcher/Launcher-jdk.jdeps.gmk index 5448946f93b..6cbcaf47163 100644 --- a/jdk/make/launcher/Launcher-jdk.jdeps.gmk +++ b/jdk/make/launcher/Launcher-jdk.jdeps.gmk @@ -25,12 +25,14 @@ include LauncherCommon.gmk -$(eval $(call SetupLauncher,javap, \ - -DEXPAND_CLASSPATH_WILDCARDS \ - -DNEVER_ACT_AS_SERVER_CLASS_MACHINE \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.javap.Main"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, javap, \ + MAIN_CLASS := com.sun.tools.javap.Main, \ + CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \ + -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \ +)) -$(eval $(call SetupLauncher,jdeps, \ - -DEXPAND_CLASSPATH_WILDCARDS \ - -DNEVER_ACT_AS_SERVER_CLASS_MACHINE \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.jdeps.Main"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, jdeps, \ + MAIN_CLASS := com.sun.tools.jdeps.Main, \ + CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \ + -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \ +)) diff --git a/jdk/make/launcher/Launcher-jdk.jdi.gmk b/jdk/make/launcher/Launcher-jdk.jdi.gmk index 9d05f255626..acb2a7125ba 100644 --- a/jdk/make/launcher/Launcher-jdk.jdi.gmk +++ b/jdk/make/launcher/Launcher-jdk.jdi.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ include LauncherCommon.gmk -$(eval $(call SetupLauncher,jdb, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.example.debug.tty.TTY"$(COMMA) }' \ - -DAPP_CLASSPATH='{ "/lib/tools.jar"$(COMMA) "/lib/sa-jdi.jar"$(COMMA) "/classes" }')) - +$(eval $(call SetupBuildLauncher, jdb, \ + MAIN_CLASS := com.sun.tools.example.debug.tty.TTY, \ + APP_CLASSPATH := /lib/tools.jar /lib/sa-jdi.jar /classes, \ +)) diff --git a/jdk/make/launcher/Launcher-jdk.jshell.gmk b/jdk/make/launcher/Launcher-jdk.jshell.gmk index ca1a69d0d67..b03f044c9c3 100644 --- a/jdk/make/launcher/Launcher-jdk.jshell.gmk +++ b/jdk/make/launcher/Launcher-jdk.jshell.gmk @@ -25,7 +25,8 @@ include LauncherCommon.gmk -$(eval $(call SetupLauncher,jshell, \ - -DEXPAND_CLASSPATH_WILDCARDS \ - -DNEVER_ACT_AS_SERVER_CLASS_MACHINE \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "jdk.internal.jshell.tool.JShellTool"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, jshell, \ + MAIN_CLASS := jdk.internal.jshell.tool.JShellTool, \ + CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \ + -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \ +)) diff --git a/jdk/make/launcher/Launcher-jdk.jvmstat.gmk b/jdk/make/launcher/Launcher-jdk.jvmstat.gmk index b93ef16716e..ee0ba2ad61d 100644 --- a/jdk/make/launcher/Launcher-jdk.jvmstat.gmk +++ b/jdk/make/launcher/Launcher-jdk.jvmstat.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,6 @@ include LauncherCommon.gmk -$(eval $(call SetupLauncher,jstatd, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.tools.jstatd.Jstatd"$(COMMA) }')) - +$(eval $(call SetupBuildLauncher, jstatd, \ + MAIN_CLASS := sun.tools.jstatd.Jstatd, \ +)) diff --git a/jdk/make/launcher/Launcher-jdk.pack200.gmk b/jdk/make/launcher/Launcher-jdk.pack200.gmk index 11611623a3b..425363c7856 100644 --- a/jdk/make/launcher/Launcher-jdk.pack200.gmk +++ b/jdk/make/launcher/Launcher-jdk.pack200.gmk @@ -25,8 +25,9 @@ include LauncherCommon.gmk -$(eval $(call SetupLauncher,pack200, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.java.util.jar.pack.Driver"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, pack200, \ + MAIN_CLASS := com.sun.java.util.jar.pack.Driver, \ +)) ################################################################################ # The order of the object files on the link command line affects the size of the resulting @@ -92,7 +93,7 @@ $(eval $(call SetupNativeCompilation,BUILD_UNPACKEXE, \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS := $(UNPACKEXE_LIBS) $(LIBCXX), \ LIBS_solaris := -lc, \ - OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpackexe$(OUTPUT_SUBDIR), \ + OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpackexe, \ OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/modules_cmds/$(MODULE), \ PROGRAM := unpack200, \ VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \ diff --git a/jdk/make/launcher/Launcher-jdk.policytool.gmk b/jdk/make/launcher/Launcher-jdk.policytool.gmk index 133e3f612d8..26ec6a4b96a 100644 --- a/jdk/make/launcher/Launcher-jdk.policytool.gmk +++ b/jdk/make/launcher/Launcher-jdk.policytool.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,8 @@ include LauncherCommon.gmk ifndef BUILD_HEADLESS_ONLY - $(eval $(call SetupLauncher,policytool, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.security.tools.policytool.PolicyTool"$(COMMA) }',, \ - $(XLIBS))) + $(eval $(call SetupBuildLauncher, policytool, \ + MAIN_CLASS := sun.security.tools.policytool.PolicyTool, \ + LIBS_unix := $(X_LIBS), \ + )) endif diff --git a/jdk/make/launcher/Launcher-jdk.rmic.gmk b/jdk/make/launcher/Launcher-jdk.rmic.gmk index 2fc8742497c..d60c3d9b60b 100644 --- a/jdk/make/launcher/Launcher-jdk.rmic.gmk +++ b/jdk/make/launcher/Launcher-jdk.rmic.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ include LauncherCommon.gmk -$(eval $(call SetupLauncher,rmic, \ - -DEXPAND_CLASSPATH_WILDCARDS \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.rmi.rmic.Main"$(COMMA) }')) - +$(eval $(call SetupBuildLauncher, rmic, \ + MAIN_CLASS := sun.rmi.rmic.Main, \ + CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ +)) diff --git a/jdk/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk b/jdk/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk index 87353a2d3e9..4b3049cbc09 100644 --- a/jdk/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk +++ b/jdk/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ include LauncherCommon.gmk -$(eval $(call SetupLauncher,jjs, \ - -DENABLE_ARG_FILES \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "jdk.nashorn.tools.jjs.Main"$(COMMA) }')) - +$(eval $(call SetupBuildLauncher, jjs, \ + MAIN_CLASS := jdk.nashorn.tools.jjs.Main, \ + CFLAGS := -DENABLE_ARG_FILES, \ +)) diff --git a/jdk/make/launcher/Launcher-jdk.xml.bind.gmk b/jdk/make/launcher/Launcher-jdk.xml.bind.gmk index 5dd0ff0fce4..19ede8880b6 100644 --- a/jdk/make/launcher/Launcher-jdk.xml.bind.gmk +++ b/jdk/make/launcher/Launcher-jdk.xml.bind.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,10 @@ include LauncherCommon.gmk -$(eval $(call SetupLauncher,schemagen, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.internal.jxc.SchemaGenerator"$(COMMA) }')) - -$(eval $(call SetupLauncher,xjc, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.internal.xjc.Driver"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, schemagen, \ + MAIN_CLASS := com.sun.tools.internal.jxc.SchemaGenerator, \ +)) +$(eval $(call SetupBuildLauncher, xjc, \ + MAIN_CLASS := com.sun.tools.internal.xjc.Driver, \ +)) diff --git a/jdk/make/launcher/Launcher-jdk.xml.ws.gmk b/jdk/make/launcher/Launcher-jdk.xml.ws.gmk index 4085ba1a967..9a5bbeff599 100644 --- a/jdk/make/launcher/Launcher-jdk.xml.ws.gmk +++ b/jdk/make/launcher/Launcher-jdk.xml.ws.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,10 @@ include LauncherCommon.gmk -$(eval $(call SetupLauncher,wsgen, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.internal.ws.WsGen"$(COMMA) }')) - -$(eval $(call SetupLauncher,wsimport, \ - -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.internal.ws.WsImport"$(COMMA) }')) +$(eval $(call SetupBuildLauncher, wsgen, \ + MAIN_CLASS := com.sun.tools.internal.ws.WsGen, \ +)) +$(eval $(call SetupBuildLauncher, wsimport, \ + MAIN_CLASS := com.sun.tools.internal.ws.WsImport, \ +)) diff --git a/jdk/make/launcher/LauncherCommon.gmk b/jdk/make/launcher/LauncherCommon.gmk index 0065114e687..942224f4697 100644 --- a/jdk/make/launcher/LauncherCommon.gmk +++ b/jdk/make/launcher/LauncherCommon.gmk @@ -28,28 +28,17 @@ include NativeCompilation.gmk # Prepare the find cache. $(eval $(call FillCacheFind, $(JDK_TOPDIR)/src/java.base/share/native/launcher)) -# When building a legacy overlay image (on solaris 64 bit), the launchers -# need to be built with a different rpath and a different output dir. -ifeq ($(OVERLAY_IMAGES), true) - ORIGIN_ROOT := /../.. - OUTPUT_SUBDIR := $(OPENJDK_TARGET_CPU_ISADIR) -else - ORIGIN_ROOT := /.. -endif - ifeq ($(OPENJDK_TARGET_OS), macosx) ORIGIN_ARG := $(call SET_EXECUTABLE_ORIGIN) else - ORIGIN_ARG := $(call SET_EXECUTABLE_ORIGIN,$(ORIGIN_ROOT)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/jli) -endif + ORIGIN_ARG := $(call SET_EXECUTABLE_ORIGIN,/../lib$(OPENJDK_TARGET_CPU_LIBDIR)/jli) -# -# Applications expect to be able to link against libjawt without invoking -# System.loadLibrary("jawt") first. This was the behaviour described in the -# devloper documentation of JAWT and what worked with OpenJDK6. -# -ifneq ($(findstring $(OPENJDK_TARGET_OS), linux solaris), ) - ORIGIN_ARG += $(call SET_EXECUTABLE_ORIGIN,$(ORIGIN_ROOT)/lib$(OPENJDK_TARGET_CPU_LIBDIR)) + # Applications expect to be able to link against libjawt without invoking + # System.loadLibrary("jawt") first. This was the behaviour described in the + # devloper documentation of JAWT and what worked with OpenJDK6. + ifneq ($(findstring $(OPENJDK_TARGET_OS), linux solaris), ) + ORIGIN_ARG += $(call SET_EXECUTABLE_ORIGIN,/../lib$(OPENJDK_TARGET_CPU_LIBDIR)) + endif endif LAUNCHER_SRC := $(JDK_TOPDIR)/src/java.base/share/native/launcher @@ -61,51 +50,78 @@ LAUNCHER_CFLAGS := -I$(JDK_TOPDIR)/src/java.base/share/native/launcher \ GLOBAL_VERSION_INFO_RESOURCE := $(JDK_TOPDIR)/src/java.base/windows/native/common/version.rc JAVA_VERSION_INFO_RESOURCE := $(JDK_TOPDIR)/src/java.base/windows/native/launcher/java.rc MACOSX_PLIST_DIR := $(JDK_TOPDIR)/src/java.base/macosx/native/launcher -# Until the shuffle is permanent, we can't add this in configure -CFLAGS_JDKEXE := $(filter-out %javavm/export, $(CFLAGS_JDKEXE)) -CFLAGS_JDKEXE += -I$(JDK_TOPDIR)/src/java.base/share/native/include \ - -I$(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/include -CXXFLAGS_JDKEXE := $(filter-out %javavm/export, $(CXXFLAGS_JDKEXE)) -CXXFLAGS_JDKEXE += -I$(JDK_TOPDIR)/src/java.base/share/native/include \ - -I$(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/include JAVA_MANIFEST := $(JDK_TOPDIR)/src/java.base/windows/native/launcher/java.manifest -define SetupLauncher - # TODO: Fix mapfile on solaris. Won't work with ld as linker. - # Parameter 1 is the name of the launcher (java, javac, jar...) - # Parameter 2 is extra CFLAGS - # Parameter 3 is extra LDFLAGS - # Parameter 4 is extra LIBS_unix - # Parameter 5 is extra LIBS_windows - # Parameter 6 is optional Windows JLI library (full path) - # Parameter 7 is optional Windows resource (RC) flags - # Parameter 8 is optional Windows version resource file (.rc) - # Parameter 9 is different output dir - # Parameter 10 if set, link statically with c runtime on windows. - # Parameter 11 if set, override plist file on macosx. - $(call LogSetupMacroEntry,SetupLauncher($1),$2,$3,$4,$5,$6,$7,$8,$9,$(10),$(11)) - $(if $(13),$(error Internal makefile error: Too many arguments to SetupLauncher, please update CompileLaunchers.gmk)) +################################################################################ +# Build standard launcher. - $1_WINDOWS_JLI_LIB := $(SUPPORT_OUTPUTDIR)/native/java.base/libjli/jli.lib - ifneq ($6, ) - $1_WINDOWS_JLI_LIB := $6 - endif - $1_VERSION_INFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE) - ifneq ($8, ) - $1_VERSION_INFO_RESOURCE := $8 +# Setup make rules for building a standard launcher. +# +# Parameter 1 is the name of the rule. This name is used as variable prefix, +# and the targets generated are listed in a variable by that name. It is also +# used as the name of the executable. +# +# Remaining parameters are named arguments. These include: +# MAIN_CLASS The Java main class to launch +# JAVA_ARGS Processed into a -DJAVA_ARGS C flag +# APP_CLASSPATH Processed into a -DAPP_CLASSPATH C flag +# CFLAGS Additional CFLAGS +# CFLAGS_windows Additional CFLAGS_windows +# LIBS_unix Additional LIBS_unix +# LIBS_windows Additional LIBS_windows +# LDFLAGS_solaris Additional LDFLAGS_solaris +# RC_FLAGS Additional RC_FLAGS +# MACOSX_SIGNED On macosx, sign this binary +# WINDOWS_STATIC_LINK On windows, link statically with C runtime and libjli. +# OPTIMIZATION Override default optimization level (LOW) +# OUTPUT_DIR Override default output directory +# VERSION_INFO_RESOURCE Override default Windows resource file +# NO_JAVA_MS Do not add -ms8m to JAVA_ARGS. +SetupBuildLauncher = $(NamedParamsMacroTemplate) +define SetupBuildLauncherBody + # Setup default values (unless overridden) + ifeq ($$($1_VERSION_INFO_RESOURCE), ) + $1_VERSION_INFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE) + endif + + ifeq ($$($1_OUTPUT_DIR), ) + $1_OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/modules_cmds/$(MODULE) + endif + + ifeq ($$($1_OPTIMIZATION), ) + $1_OPTIMIZATION := LOW + endif + + ifneq ($$($1_NO_JAVA_MS), true) + # The norm is to append -ms8m, unless otherwise instructed. + $1_JAVA_ARGS += -ms8m + endif + + ifneq ($$($1_JAVA_ARGS), ) + $1_JAVA_ARGS_STR := '{ $$(strip $$(foreach a, \ + $$(addprefix -J, $$($1_JAVA_ARGS)) $$($1_MAIN_CLASS), "$$a"$(COMMA) )) }' + $1_CFLAGS += -DJAVA_ARGS=$$($1_JAVA_ARGS_STR) + endif + + ifneq ($$($1_APP_CLASSPATH), ) + $1_APP_CLASSPATH_STR := '{ $$(strip $$(foreach a, \ + $$($1_APP_CLASSPATH), "$$a"$(COMMA) )) }' + # Remove the trailing comma + $1_APP_CLASSPATH_STR := $$(strip $$(subst $$(COMMA) }', }', \ + $$($1_APP_CLASSPATH_STR))) + $1_CFLAGS += -DAPP_CLASSPATH=$$($1_APP_CLASSPATH_STR) endif - $1_LDFLAGS := $3 $1_LIBS := ifeq ($(OPENJDK_TARGET_OS), macosx) - $1_PLIST_FILE := Info-cmdline.plist - ifneq ($(11), ) - $1_PLIST_FILE := $(11) - ifneq ($$(findstring privileged, $$($1_PLIST_FILE)), ) + ifeq ($$($1_MACOSX_SIGNED), true) + $1_PLIST_FILE := Info-privileged.plist $1_CODESIGN := true - endif + else + $1_PLIST_FILE := Info-cmdline.plist endif + $1_CFLAGS += -DPACKAGE_PATH='"$(PACKAGE_PATH)"' $1_LDFLAGS += -Wl,-all_load $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a \ -sectcreate __TEXT __info_plist $(MACOSX_PLIST_DIR)/$$($1_PLIST_FILE) $1_LIBS += -framework Cocoa -framework Security \ @@ -121,22 +137,12 @@ define SetupLauncher $1_LIBS += -lz endif - $1_OUTPUT_DIR_ARG := $9 - ifeq (, $$($1_OUTPUT_DIR_ARG)) - $1_OUTPUT_DIR_ARG := $(SUPPORT_OUTPUTDIR)/modules_cmds/$(MODULE) - endif - - # TODO: maybe it's better to move this if-statement out of this function - ifeq ($1, java) - $1_OPTIMIZATION_ARG := HIGH - $1_LDFLAGS_solaris := -R$(OPENWIN_HOME)/lib$(OPENJDK_TARGET_CPU_ISADIR) + ifeq ($$($1_WINDOWS_STATIC_LINK), true) + $1_CFLAGS += $(filter-out -MD, $(CFLAGS_JDKEXE)) + $1_WINDOWS_JLI_LIB := $(SUPPORT_OUTPUTDIR)/native/java.base/jli_static.lib else - $1_OPTIMIZATION_ARG := LOW - endif - - $1_CFLAGS := $(CFLAGS_JDKEXE) - ifeq ($(10), true) - $1_CFLAGS := $(filter-out -MD, $(CFLAGS_JDKEXE)) + $1_CFLAGS += $(CFLAGS_JDKEXE) + $1_WINDOWS_JLI_LIB := $(SUPPORT_OUTPUTDIR)/native/java.base/libjli/jli.lib endif # The linker on older SuSE distros (e.g. on SLES 10) complains with: @@ -156,22 +162,23 @@ define SetupLauncher endif endif - $(call SetupNativeCompilation,BUILD_LAUNCHER_$1, \ + $$(eval $$(call SetupNativeCompilation, BUILD_LAUNCHER_$1, \ SRC := $(LAUNCHER_SRC), \ INCLUDE_FILES := main.c, \ - OPTIMIZATION := $$($1_OPTIMIZATION_ARG), \ + OPTIMIZATION := $$($1_OPTIMIZATION), \ CFLAGS := $$($1_CFLAGS) \ $(LAUNCHER_CFLAGS) \ -DFULL_VERSION='"$(FULL_VERSION)"' \ -DJDK_MAJOR_VERSION='"$(JDK_MAJOR_VERSION)"' \ -DJDK_MINOR_VERSION='"$(JDK_MINOR_VERSION)"' \ -DLAUNCHER_NAME='"$(LAUNCHER_NAME)"' \ - -DPROGNAME='"$1"' $(DPACKAGEPATH) \ - $2, \ + -DPROGNAME='"$1"' \ + $$($1_CFLAGS), \ CFLAGS_linux := -fPIC, \ CFLAGS_solaris := -KPIC -DHAVE_GETHRTIME, \ + CFLAGS_windows := $$($1_CFLAGS_windows), \ LDFLAGS := $(LDFLAGS_JDKEXE) \ - $(ORIGIN_ARG) \ + $$(ORIGIN_ARG) \ $$($1_LDFLAGS), \ LDFLAGS_linux := \ $(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)) \ @@ -182,27 +189,29 @@ define SetupLauncher -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base$(OPENJDK_TARGET_CPU_LIBDIR)/jli, \ MAPFILE := $$($1_MAPFILE), \ LIBS := $(JDKEXE_LIBS) $$($1_LIBS), \ - LIBS_unix := $4, \ + LIBS_unix := $$($1_LIBS_unix), \ LIBS_linux := -lpthread -ljli $(LIBDL) -lc, \ LIBS_solaris := -ljli -lthread $(LIBDL) -lc, \ LIBS_windows := $$($1_WINDOWS_JLI_LIB) \ - $(SUPPORT_OUTPUTDIR)/native/java.base/libjava/java.lib advapi32.lib $5, \ - OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/$1_objs$(OUTPUT_SUBDIR), \ - OUTPUT_DIR := $$($1_OUTPUT_DIR_ARG)$(OUTPUT_SUBDIR), \ + $(SUPPORT_OUTPUTDIR)/native/java.base/libjava/java.lib advapi32.lib \ + $$($1_LIBS_windows), \ + OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/$1_objs, \ + OUTPUT_DIR := $$($1_OUTPUT_DIR), \ PROGRAM := $1, \ DEBUG_SYMBOLS := true, \ VERSIONINFO_RESOURCE := $$($1_VERSION_INFO_RESOURCE), \ - RC_FLAGS := $(RC_FLAGS) \ + RC_FLAGS := $$(RC_FLAGS) \ -D "JDK_FNAME=$1$(EXE_SUFFIX)" \ -D "JDK_INTERNAL_NAME=$1" \ -D "JDK_FTYPE=0x1L" \ - $7, \ + $$($1_RC_FLAGS), \ MANIFEST := $(JAVA_MANIFEST), \ MANIFEST_VERSION := $(JDK_VERSION_FOR_MANIFEST), \ CODESIGN := $$($1_CODESIGN), \ - ) + )) - TARGETS += $$(BUILD_LAUNCHER_$1) + $1 += $$(BUILD_LAUNCHER_$1) + TARGETS += $$($1) ifneq (,$(filter $(OPENJDK_TARGET_OS), macosx aix)) $$(BUILD_LAUNCHER_$1): $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a @@ -213,18 +222,3 @@ define SetupLauncher $$($1_WINDOWS_JLI_LIB) endif endef - -########################################################################################## - -XLIBS := $(X_LIBS) -lX11 -ifeq ($(OPENJDK_TARGET_OS), macosx) - DPACKAGEPATH := -DPACKAGE_PATH='"$(PACKAGE_PATH)"' - XLIBS := -endif - -JAVA_RC_FLAGS += -i $(JDK_TOPDIR)/src/java.base/windows/native/common -ifdef OPENJDK - JAVA_RC_FLAGS += -i "$(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons" -else - JAVA_RC_FLAGS += -i "$(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons" -endif From f10554d7c202f35164edd1324bba3c4db70c6789 Mon Sep 17 00:00:00 2001 From: Lance Andersen Date: Thu, 5 Nov 2015 10:37:08 -0500 Subject: [PATCH 28/31] 8136496: Add Connection.begin/endRequest Reviewed-by: joehw, rriggs, psandoz --- .../share/classes/java/sql/Connection.java | 107 +++++++++++++++++- .../classes/javax/sql/PooledConnection.java | 13 ++- 2 files changed, 117 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.sql/share/classes/java/sql/Connection.java b/jdk/src/java.sql/share/classes/java/sql/Connection.java index ac5d3158b6e..880c2cb3904 100644 --- a/jdk/src/java.sql/share/classes/java/sql/Connection.java +++ b/jdk/src/java.sql/share/classes/java/sql/Connection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1482,4 +1482,109 @@ throws SQLException; * @since 1.7 */ int getNetworkTimeout() throws SQLException; + + // JDBC 4.3 + + /** + * Hints to the driver that a request, an independent unit of work, is beginning + * on this connection. Each request is independent of all other requests + * with regard to state local to the connection either on the client or the + * server. Work done between {@code beginRequest}, {@code endRequest} + * pairs does not depend on any other work done on the connection either as + * part of another request or outside of any request. A request may include multiple + * transactions. There may be dependencies on committed database state as + * that is not local to the connection. + *

    + * Local state is defined as any state associated with a Connection that is + * local to the current Connection either in the client or the database that + * is not transparently reproducible. + *

    + * Calls to {@code beginRequest} and {@code endRequest} are not nested. + * Multiple calls to {@code beginRequest} without an intervening call + * to {@code endRequest} is not an error. The first {@code beginRequest} call + * marks the start of the request and subsequent calls are treated as + * a no-op + *

    + * Use of {@code beginRequest} and {@code endRequest} is optional, vendor + * specific and should largely be transparent. In particular + * implementations may detect conditions that indicate dependence on + * other work such as an open transaction. It is recommended though not + * required that implementations throw a {@code SQLException} if there is an active + * transaction and {@code beginRequest} is called. + * Using these methods may improve performance or provide other benefits. + * Consult your vendors documentation for additional information. + *

    + * It is recommended to + * enclose each unit of work in {@code beginRequest}, {@code endRequest} + * pairs such that there is no open transaction at the beginning or end of + * the request and no dependency on local state that crosses request + * boundaries. Committed database state is not local. + * + * @implSpec + * The default implementation is a no-op. + *

    + * @apiNote + * This method is to be used by Connection pooling managers. + *

    + * The pooling manager should call {@code beginRequest} on the underlying connection + * prior to returning a connection to the caller. + *

    + * The pooling manager does not need to call {@code beginRequest} if: + *

      + *
    • The connection pool caches {@code PooledConnection} objects
    • + *
    • Returns a logical connection handle when {@code getConnection} is + * called by the application
    • + *
    • The pool manager calls {@code Connection.close} on the logical connection handle + * prior to returning the {@code PooledConnection} back to the cache
    • + *
    + * @throws SQLException if an error occurs + * @since 1.9 + * @see endRequest + * @see PooledConnection + */ + default void beginRequest() throws SQLException { + // Default method takes no action + } + + /** + * Hints to the driver that a request, an independent unit of work, + * has completed. Calls to {@code beginRequest} + * and {@code endRequest} are not nested. Multiple + * calls to {@code endRequest} without an intervening call to {@code beginRequest} + * is not an error. The first {@code endRequest} call + * marks the request completed and subsequent calls are treated as + * a no-op. If {@code endRequest} is called without an initial call to + * {@code beginRequest} is a no-op. + *

    + * The exact behavior of this method is vendor specific. In particular + * implementations may detect conditions that indicate dependence on + * other work such as an open transaction. It is recommended though not + * required that implementations throw a {@code SQLException} if there is an active + * transaction and {@code endRequest} is called. + * + * @implSpec + * The default implementation is a no-op. + * @apiNote + * + * This method is to be used by Connection pooling managers. + *

    + * The pooling manager should call {@code endRequest} on the underlying connection + * when the applications returns the connection back to the connection pool. + * + *

  • The connection pool caches {@code PooledConnection} objects
  • + *
  • Returns a logical connection handle when {@code getConnection} is + * called by the application
  • + *
  • The pool manager calls {@code Connection.close} on the logical connection handle + * prior to returning the {@code PooledConnection} back to the cache
  • + * + * @throws SQLException if an error occurs + * @since 1.9 + * @see beginRequest + * @see PooledConnection + */ + default void endRequest() throws SQLException { + // Default method takes no action + } } diff --git a/jdk/src/java.sql/share/classes/javax/sql/PooledConnection.java b/jdk/src/java.sql/share/classes/javax/sql/PooledConnection.java index c16e73bdeec..50b0acd85d2 100644 --- a/jdk/src/java.sql/share/classes/javax/sql/PooledConnection.java +++ b/jdk/src/java.sql/share/classes/javax/sql/PooledConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,7 +66,16 @@ import java.sql.SQLException; * PooledConnection object to the pool of connections so that * it can be used again. Thus, when an application closes its connection, * the underlying physical connection is recycled rather than being closed. - *

    + *

    + * If the connection pool manager wraps or provides a proxy to the logical + * handle returned from a call to {@code PoolConnection.getConnection}, the pool + * manager must do + * one of the following when the application calls {@code Connection.close}: + *

      + *
    • call {@code endRequest} on the logical {@code Connection} handle + *
    • call {@code close} on the logical {@code Connection} handle + *
    + *

    * The physical connection is not closed until the connection pool manager * calls the PooledConnection method close. * This method is generally called to have an orderly shutdown of the server or From 6f0997408acdbaea73ca07b82226211f9afd8579 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Thu, 5 Nov 2015 16:29:16 +0100 Subject: [PATCH 29/31] 8141539: Avoid calculating string constants in InnerClassLambdaMetaFactory Reviewed-by: vlivanov --- .../lang/invoke/InnerClassLambdaMetafactory.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java b/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java index 69d80ec0e61..5f821977c0f 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java @@ -66,15 +66,15 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace"; private static final String NAME_METHOD_READ_OBJECT = "readObject"; private static final String NAME_METHOD_WRITE_OBJECT = "writeObject"; + + private static final String DESCR_CLASS = "Ljava/lang/Class;"; + private static final String DESCR_STRING = "Ljava/lang/String;"; + private static final String DESCR_OBJECT = "Ljava/lang/Object;"; private static final String DESCR_CTOR_SERIALIZED_LAMBDA - = MethodType.methodType(void.class, - Class.class, - String.class, String.class, String.class, - int.class, String.class, String.class, String.class, - String.class, - Object[].class).toMethodDescriptorString(); - private static final String DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION - = MethodType.methodType(void.class, String.class).toMethodDescriptorString(); + = "(" + DESCR_CLASS + DESCR_STRING + DESCR_STRING + DESCR_STRING + "I" + + DESCR_STRING + DESCR_STRING + DESCR_STRING + DESCR_STRING + "[" + DESCR_OBJECT + ")V"; + + private static final String DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION = "(Ljava/lang/String;)V"; private static final String[] SER_HOSTILE_EXCEPTIONS = new String[] {NAME_NOT_SERIALIZABLE_EXCEPTION}; From 05e8afd0ef6e7fe1f2c66a7b6c8a3317d51081d2 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Thu, 5 Nov 2015 16:36:55 +0100 Subject: [PATCH 30/31] 8141536: MethodType field offset calculation could be lazy Reviewed-by: vlivanov --- .../classes/java/lang/invoke/MethodType.java | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java index 1a986a4bf64..7f77c5e84ad 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java @@ -1187,20 +1187,23 @@ s.writeObject(this.parameterArray()); // store them into the implementation-specific final fields. checkRtype(rtype); checkPtypes(ptypes); - UNSAFE.putObject(this, rtypeOffset, rtype); - UNSAFE.putObject(this, ptypesOffset, ptypes); + UNSAFE.putObject(this, OffsetHolder.rtypeOffset, rtype); + UNSAFE.putObject(this, OffsetHolder.ptypesOffset, ptypes); } - // Support for resetting final fields while deserializing - private static final long rtypeOffset, ptypesOffset; - static { - try { - rtypeOffset = UNSAFE.objectFieldOffset - (MethodType.class.getDeclaredField("rtype")); - ptypesOffset = UNSAFE.objectFieldOffset - (MethodType.class.getDeclaredField("ptypes")); - } catch (Exception ex) { - throw new Error(ex); + // Support for resetting final fields while deserializing. Implement Holder + // pattern to make the rarely needed offset calculation lazy. + private static class OffsetHolder { + private static final long rtypeOffset, ptypesOffset; + static { + try { + rtypeOffset = UNSAFE.objectFieldOffset + (MethodType.class.getDeclaredField("rtype")); + ptypesOffset = UNSAFE.objectFieldOffset + (MethodType.class.getDeclaredField("ptypes")); + } catch (Exception ex) { + throw new Error(ex); + } } } From c00f85ddb188e2860707a250870102339735ed93 Mon Sep 17 00:00:00 2001 From: Lance Andersen Date: Thu, 5 Nov 2015 14:57:27 -0500 Subject: [PATCH 31/31] 8141546: Fix javadoc warnings in Connection due to 8136496 Reviewed-by: alanb --- jdk/src/java.sql/share/classes/java/sql/Connection.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.sql/share/classes/java/sql/Connection.java b/jdk/src/java.sql/share/classes/java/sql/Connection.java index 880c2cb3904..40aa3de0730 100644 --- a/jdk/src/java.sql/share/classes/java/sql/Connection.java +++ b/jdk/src/java.sql/share/classes/java/sql/Connection.java @@ -1540,7 +1540,7 @@ throws SQLException; * @throws SQLException if an error occurs * @since 1.9 * @see endRequest - * @see PooledConnection + * @see javax.sql.PooledConnection */ default void beginRequest() throws SQLException { // Default method takes no action @@ -1570,7 +1570,7 @@ throws SQLException; *

    * The pooling manager should call {@code endRequest} on the underlying connection * when the applications returns the connection back to the connection pool. - * * The pooling manager does not need to call {@code endRequest} if: *

      *
    • The connection pool caches {@code PooledConnection} objects
    • @@ -1582,7 +1582,7 @@ throws SQLException; * @throws SQLException if an error occurs * @since 1.9 * @see beginRequest - * @see PooledConnection + * @see javax.sql.PooledConnection */ default void endRequest() throws SQLException { // Default method takes no action