--- a/.hgtags-top-repo Thu Sep 18 13:27:06 2014 -0700
+++ b/.hgtags-top-repo Wed Jul 05 20:01:44 2017 +0200
@@ -273,3 +273,4 @@
ea2f7981236f3812436958748ab3d26e80a35130 jdk9-b28
9e6581aeda388a23fbee021fc33e6aa152a60657 jdk9-b29
36e9bc875325813ac9c44ac0c617a463091fa9f5 jdk9-b30
+69a84c16d9c28e0e3d504b9c8766c24bafcd58f6 jdk9-b31
--- a/Makefile Thu Sep 18 13:27:06 2014 -0700
+++ b/Makefile Wed Jul 05 20:01:44 2017 +0200
@@ -70,8 +70,8 @@
# Run the makefile with an arbitrary SPEC using -p -q (quiet dry-run and dump rules) to find
# available PHONY targets. Use this list as valid targets to pass on to the repeated calls.
all_phony_targets := $(sort $(filter-out $(global_targets), $(strip $(shell \
- cd $(root_dir)/make && $(MAKE) -f Main.gmk -p -q FRC SPEC=$(firstword $(SPEC)) | \
- grep "^.PHONY:" | head -n 1 | cut -d " " -f 2-))))
+ cd $(root_dir)/make && $(MAKE) -f Main.gmk -p -q FRC SPEC=$(firstword $(SPEC)) \
+ -I $(root_dir)/make/common | grep "^.PHONY:" | head -n 1 | cut -d " " -f 2-))))
# Loop through the configurations and call the main-wrapper for each one. The wrapper
# target will execute with a single configuration loaded.
@@ -115,12 +115,12 @@
main-wrapper:
ifneq ($(SEQUENTIAL_TARGETS), )
- (cd $(root_dir)/make && $(MAKE) -f Main.gmk SPEC=$(SPEC) -j 1 \
+ (cd $(SRC_ROOT)/make && $(MAKE) -f Main.gmk SPEC=$(SPEC) -j 1 \
$(VERBOSE) VERBOSE=$(VERBOSE) LOG_LEVEL=$(LOG_LEVEL) $(SEQUENTIAL_TARGETS))
endif
ifneq ($(PARALLEL_TARGETS), )
@$(call AtMakeStart)
- (cd $(root_dir)/make && $(BUILD_LOG_WRAPPER) $(MAKE) -f Main.gmk SPEC=$(SPEC) -j $(JOBS) \
+ (cd $(SRC_ROOT)/make && $(BUILD_LOG_WRAPPER) $(MAKE) -f Main.gmk SPEC=$(SPEC) -j $(JOBS) \
$(VERBOSE) VERBOSE=$(VERBOSE) LOG_LEVEL=$(LOG_LEVEL) $(PARALLEL_TARGETS) \
$(if $(filter true, $(OUTPUT_SYNC_SUPPORTED)), -O$(OUTPUT_SYNC)))
@$(call AtMakeEnd)
--- a/common/autoconf/generated-configure.sh Thu Sep 18 13:27:06 2014 -0700
+++ b/common/autoconf/generated-configure.sh Wed Jul 05 20:01:44 2017 +0200
@@ -4327,7 +4327,7 @@
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1410377275
+DATE_WHEN_GENERATED=1410791401
###############################################################################
#
@@ -14642,7 +14642,7 @@
FASTDEBUG="false"
DEBUG_CLASSFILES="true"
BUILD_VARIANT_RELEASE="-debug"
- HOTSPOT_DEBUG_LEVEL="jvmg"
+ HOTSPOT_DEBUG_LEVEL="debug"
HOTSPOT_EXPORT="debug"
;;
optimized )
--- a/common/autoconf/hotspot-spec.gmk.in Thu Sep 18 13:27:06 2014 -0700
+++ b/common/autoconf/hotspot-spec.gmk.in Wed Jul 05 20:01:44 2017 +0200
@@ -97,8 +97,6 @@
endif
HOTSPOT_MAKE_ARGS:=@HOTSPOT_MAKE_ARGS@ @STATIC_CXX_SETTING@
-# This is used from the libjvm build for C/C++ code.
-HOTSPOT_BUILD_JOBS:=$(JOBS)
# Control wether Hotspot runs Queens test after building
TEST_IN_BUILD=@TEST_IN_BUILD@
--- a/common/autoconf/jdk-options.m4 Thu Sep 18 13:27:06 2014 -0700
+++ b/common/autoconf/jdk-options.m4 Wed Jul 05 20:01:44 2017 +0200
@@ -234,7 +234,7 @@
FASTDEBUG="false"
DEBUG_CLASSFILES="true"
BUILD_VARIANT_RELEASE="-debug"
- HOTSPOT_DEBUG_LEVEL="jvmg"
+ HOTSPOT_DEBUG_LEVEL="debug"
HOTSPOT_EXPORT="debug"
;;
optimized )
--- a/common/autoconf/spec.gmk.in Thu Sep 18 13:27:06 2014 -0700
+++ b/common/autoconf/spec.gmk.in Wed Jul 05 20:01:44 2017 +0200
@@ -245,6 +245,7 @@
NASHORN_OUTPUTDIR=$(BUILD_OUTPUT)/nashorn
IMAGES_OUTPUTDIR=$(BUILD_OUTPUT)/images
TESTMAKE_OUTPUTDIR=$(BUILD_OUTPUT)/testmake
+MAKESUPPORT_OUTPUTDIR=$(BUILD_OUTPUT)/make-support
LANGTOOLS_DIST=$(LANGTOOLS_OUTPUTDIR)/dist
CORBA_DIST=$(CORBA_OUTPUTDIR)/dist
--- a/common/bin/unshuffle_list.txt Thu Sep 18 13:27:06 2014 -0700
+++ b/common/bin/unshuffle_list.txt Wed Jul 05 20:01:44 2017 +0200
@@ -1216,14 +1216,13 @@
jdk/src/java.security.acl/share/classes/sun/security/acl : jdk/src/share/classes/sun/security/acl
jdk/src/java.security.jgss/macosx/native/libosxkrb5/nativeccache.c : jdk/src/share/native/sun/security/krb5/nativeccache.c
jdk/src/java.security.jgss/macosx/native/libosxkrb5/SCDynamicStoreConfig.m : jdk/src/macosx/native/sun/security/krb5/SCDynamicStoreConfig.m
-jdk/src/java.security.jgss/share/classes/com/sun/security/jgss : jdk/src/share/classes/com/sun/security/jgss
-jdk/src/java.security.jgss/share/classes/com/sun/security/sasl/gsskerb : jdk/src/share/classes/com/sun/security/sasl/gsskerb
jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos : jdk/src/share/classes/javax/security/auth/kerberos
jdk/src/java.security.jgss/share/classes/jgss-overview.html : jdk/src/share/classes/com/sun/security/jgss/jgss-overview.html
jdk/src/java.security.jgss/share/classes/org/ietf/jgss : jdk/src/share/classes/org/ietf/jgss
jdk/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego : jdk/src/share/classes/sun/net/www/protocol/http/spnego
jdk/src/java.security.jgss/share/classes/sun/security/jgss : jdk/src/share/classes/sun/security/jgss
jdk/src/java.security.jgss/share/classes/sun/security/krb5 : jdk/src/share/classes/sun/security/krb5
+jdk/src/java.security.jgss/windows/classes/sun/security/krb5 : jdk/src/windows/classes/sun/security/krb5
jdk/src/java.security.jgss/share/classes/sun/security/ssl/krb5 : jdk/src/share/classes/sun/security/ssl/krb5
jdk/src/java.security.jgss/share/native/libj2gss : jdk/src/share/native/sun/security/jgss/wrapper
jdk/src/java.security.jgss/unix/native/libj2gss : jdk/src/solaris/native/sun/security/jgss/wrapper
@@ -1477,6 +1476,8 @@
jdk/src/jdk.security.auth/share/classes/jaas-overview.html : jdk/src/share/classes/com/sun/security/auth/jaas-overview.html
jdk/src/jdk.security.auth/unix/native/libjaas : jdk/src/solaris/native/com/sun/security/auth/module
jdk/src/jdk.security.auth/windows/native/libjaas : jdk/src/windows/native/com/sun/security/auth/module
+jdk/src/jdk.security.jgss/share/classes/com/sun/security/jgss : jdk/src/share/classes/com/sun/security/jgss
+jdk/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb : jdk/src/share/classes/com/sun/security/sasl/gsskerb
jdk/src/jdk.snmp/share/classes/com/sun/jmx/snmp : jdk/src/share/classes/com/sun/jmx/snmp
jdk/src/jdk.snmp/share/classes/sun/management/snmp : jdk/src/share/classes/sun/management/snmp
jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs : jdk/src/share/classes/jdk/nio/zipfs
--- a/corba/.hgtags Thu Sep 18 13:27:06 2014 -0700
+++ b/corba/.hgtags Wed Jul 05 20:01:44 2017 +0200
@@ -273,3 +273,4 @@
a00b04ef067e39f50b9a0fea6f1904e35d632a73 jdk9-b28
163a9cd806fd09970baf1f5f42b92a3cfe7ee945 jdk9-b29
98967ae6ae53ebf15615e07cd5a6b1ae04dfd84c jdk9-b30
+c432b80aadd0cb2b2361b02add4d671957d4cec9 jdk9-b31
--- a/hotspot/.hgtags Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/.hgtags Wed Jul 05 20:01:44 2017 +0200
@@ -433,3 +433,4 @@
657294869d7ff063e055f5492cab7ce5612ca851 jdk9-b28
deb29e92f68ace2808a36ecfa18c7d61dcb645bb jdk9-b29
5c722dffbc0f34eb8d903dca7b261e52248fa17e jdk9-b30
+9f7d155d28e519f3e4645dc21cf185c25f3176ed jdk9-b31
--- a/hotspot/agent/src/os/win32/windbg/sawindbg.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/agent/src/os/win32/windbg/sawindbg.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -112,7 +112,9 @@
return;}
static void throwNewDebuggerException(JNIEnv* env, const char* errMsg) {
- env->ThrowNew(env->FindClass("sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
+ jclass clazz = env->FindClass("sun/jvm/hotspot/debugger/DebuggerException");
+ CHECK_EXCEPTION;
+ env->ThrowNew(clazz, errMsg);
}
/*
@@ -310,15 +312,18 @@
static bool setImageAndSymbolPath(JNIEnv* env, jobject obj) {
jboolean isCopy;
jclass clazz = env->GetObjectClass(obj);
+ CHECK_EXCEPTION_(false);
jstring path;
const char* buf;
path = (jstring) env->GetStaticObjectField(clazz, imagePath_ID);
+ CHECK_EXCEPTION_(false);
buf = env->GetStringUTFChars(path, &isCopy);
CHECK_EXCEPTION_(false);
AutoJavaString imagePath(env, path, buf);
path = (jstring) env->GetStaticObjectField(clazz, symbolPath_ID);
+ CHECK_EXCEPTION_(false);
buf = env->GetStringUTFChars(path, &isCopy);
CHECK_EXCEPTION_(false);
AutoJavaString symbolPath(env, path, buf);
--- a/hotspot/make/Makefile Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/make/Makefile Wed Jul 05 20:01:44 2017 +0200
@@ -95,6 +95,7 @@
COMMON_VM_PRODUCT_TARGETS=product product1 docs export_product
COMMON_VM_FASTDEBUG_TARGETS=fastdebug fastdebug1 docs export_fastdebug
COMMON_VM_DEBUG_TARGETS=debug debug1 docs export_debug
+COMMON_VM_OPTIMIZED_TARGETS=optimized optimized1 docs export_optimized
# JDK directory list
JDK_DIRS=bin include jre lib demo
@@ -111,20 +112,21 @@
all_product: product1 docs export_product
all_fastdebug: fastdebug1 docs export_fastdebug
all_debug: debug1 docs export_debug
+all_optimized: optimized1 docs export_optimized
else
ifeq ($(MACOSX_UNIVERSAL),true)
all_product: universal_product
all_fastdebug: universal_fastdebug
all_debug: universal_debug
+all_optimized: universal_optimized
else
all_product: $(COMMON_VM_PRODUCT_TARGETS)
all_fastdebug: $(COMMON_VM_FASTDEBUG_TARGETS)
all_debug: $(COMMON_VM_DEBUG_TARGETS)
+all_optimized: $(COMMON_VM_OPTIMIZED_TARGETS)
endif
endif
-all_optimized: optimized optimized1 docs export_optimized
-
allzero: all_productzero all_fastdebugzero
all_productzero: productzero docs export_product
all_fastdebugzero: fastdebugzero docs export_fastdebug
@@ -890,3 +892,5 @@
create_jdk copy_jdk update_jdk test_jdk \
copy_product_jdk copy_fastdebug_jdk copy_debug_jdk \
$(HS_ALT_MAKE)/Makefile.make remove_old_debuginfo
+
+.NOTPARALLEL:
--- a/hotspot/make/aix/Makefile Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/make/aix/Makefile Wed Jul 05 20:01:44 2017 +0200
@@ -256,36 +256,36 @@
$(SUBDIRS_TIERED): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=tiered
+ +$(BUILDTREE) VARIANT=tiered
$(SUBDIRS_C2): $(BUILDTREE_MAKE)
ifeq ($(FORCE_TIERED),1)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
+ +$(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
else
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=compiler2
+ +$(BUILDTREE) VARIANT=compiler2
endif
$(SUBDIRS_C1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=compiler1
+ +$(BUILDTREE) VARIANT=compiler1
$(SUBDIRS_CORE): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=core
+ +$(BUILDTREE) VARIANT=core
$(SUBDIRS_ZERO): $(BUILDTREE_MAKE) platform_zero
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
+ +$(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
$(SUBDIRS_SHARK): $(BUILDTREE_MAKE) platform_zero
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
+ +$(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
$(SUBDIRS_MINIMAL1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=minimal1
+ +$(BUILDTREE) VARIANT=minimal1
platform_zero: $(GAMMADIR)/make/$(OSNAME)/platform_zero.in
@@ -379,3 +379,5 @@
.PHONY: all compiler1 compiler2 core zero shark
.PHONY: clean clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark docs clean_docs
.PHONY: checks check_os_version check_j2se_version
+
+.NOTPARALLEL:
--- a/hotspot/make/aix/makefiles/buildtree.make Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/make/aix/makefiles/buildtree.make Wed Jul 05 20:01:44 2017 +0200
@@ -173,7 +173,7 @@
# Run make in each subdirectory recursively.
$(SUBMAKE_DIRS): $(SIMPLE_DIRS) FORCE
$(QUIETLY) [ -d $@ ] || { mkdir -p $@; }
- $(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
+ +$(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
$(QUIETLY) touch $@
$(SIMPLE_DIRS):
@@ -364,3 +364,5 @@
FORCE:
.PHONY: all FORCE
+
+.NOTPARALLEL:
--- a/hotspot/make/aix/makefiles/top.make Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/make/aix/makefiles/top.make Wed Jul 05 20:01:44 2017 +0200
@@ -69,7 +69,13 @@
# Wierd argument adjustment for "gnumake -j..."
adjust-mflags = $(GENERATED)/adjust-mflags
-MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
+# If SPEC is set, it's from configure and it's already controlling concurrency
+# for us. Skip setting -j with HOTSPOT_BUILD_JOBS.
+ifeq ($(SPEC), )
+ MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
+else
+ MFLAGS-adjusted = -r $(MFLAGS)
+endif
# default target: update lists, make vm
@@ -116,7 +122,7 @@
@+mv $@+ $@
the_vm: vm_build_preliminaries $(adjust-mflags)
- @$(UpdatePCH)
+ +@$(UpdatePCH)
@$(MAKE) -f vm.make $(MFLAGS-adjusted)
install gamma: the_vm
@@ -125,7 +131,7 @@
# next rules support "make foo.[ois]"
%.o %.i %.s:
- $(UpdatePCH)
+ +$(UpdatePCH)
$(MAKE) -f vm.make $(MFLAGS) $@
#$(MAKE) -f vm.make $@
@@ -142,3 +148,5 @@
.PHONY: default vm_build_preliminaries
.PHONY: lists ad_stuff jvmti_stuff sa_stuff the_vm clean realclean
.PHONY: checks check_os_version install
+
+.NOTPARALLEL:
--- a/hotspot/make/bsd/Makefile Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/make/bsd/Makefile Wed Jul 05 20:01:44 2017 +0200
@@ -250,36 +250,36 @@
$(SUBDIRS_TIERED): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=tiered
+ +$(BUILDTREE) VARIANT=tiered
$(SUBDIRS_C2): $(BUILDTREE_MAKE)
ifeq ($(FORCE_TIERED),1)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
+ +$(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
else
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=compiler2
+ +$(BUILDTREE) VARIANT=compiler2
endif
$(SUBDIRS_C1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=compiler1
+ +$(BUILDTREE) VARIANT=compiler1
$(SUBDIRS_CORE): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=core
+ +$(BUILDTREE) VARIANT=core
$(SUBDIRS_ZERO): $(BUILDTREE_MAKE) platform_zero
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
+ +$(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
$(SUBDIRS_SHARK): $(BUILDTREE_MAKE) platform_zero
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
+ +$(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
$(SUBDIRS_MINIMAL1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=minimal1
+ +$(BUILDTREE) VARIANT=minimal1
platform_zero: $(GAMMADIR)/make/$(OSNAME)/platform_zero.in
$(SED) 's/@ZERO_ARCHDEF@/$(ZERO_ARCHDEF)/g;s/@ZERO_LIBARCH@/$(ZERO_LIBARCH)/g;' < $< > $@
@@ -392,3 +392,5 @@
.PHONY: clean clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark docs clean_docs
.PHONY: checks check_os_version check_j2se_version
.PHONY: $(HS_ALT_MAKE)/$(OSNAME)/Makefile.make
+
+.NOTPARALLEL:
--- a/hotspot/make/bsd/makefiles/buildtree.make Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/make/bsd/makefiles/buildtree.make Wed Jul 05 20:01:44 2017 +0200
@@ -178,7 +178,7 @@
# Run make in each subdirectory recursively.
$(SUBMAKE_DIRS): $(SIMPLE_DIRS) FORCE
$(QUIETLY) [ -d $@ ] || { mkdir -p $@; }
- $(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
+ +$(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
$(QUIETLY) touch $@
$(SIMPLE_DIRS):
@@ -378,3 +378,5 @@
FORCE:
.PHONY: all FORCE
+
+.NOTPARALLEL:
--- a/hotspot/make/bsd/makefiles/top.make Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/make/bsd/makefiles/top.make Wed Jul 05 20:01:44 2017 +0200
@@ -69,7 +69,13 @@
# Wierd argument adjustment for "gnumake -j..."
adjust-mflags = $(GENERATED)/adjust-mflags
-MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
+# If SPEC is set, it's from configure and it's already controlling concurrency
+# for us. Skip setting -j with HOTSPOT_BUILD_JOBS.
+ifeq ($(SPEC), )
+ MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
+else
+ MFLAGS-adjusted = -r $(MFLAGS)
+endif
# default target: update lists, make vm
@@ -125,7 +131,7 @@
@+mv $@+ $@
the_vm: vm_build_preliminaries $(adjust-mflags)
- @$(UpdatePCH)
+ +@$(UpdatePCH)
@$(MAKE) -f vm.make $(MFLAGS-adjusted)
install : the_vm
@@ -134,7 +140,7 @@
# next rules support "make foo.[ois]"
%.o %.i %.s:
- $(UpdatePCH)
+ +$(UpdatePCH)
$(MAKE) -f vm.make $(MFLAGS) $@
#$(MAKE) -f vm.make $@
@@ -151,3 +157,5 @@
.PHONY: default vm_build_preliminaries
.PHONY: lists ad_stuff jvmti_stuff sa_stuff the_vm clean realclean
.PHONY: checks check_os_version install
+
+.NOTPARALLEL:
--- a/hotspot/make/bsd/makefiles/universal.gmk Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/make/bsd/makefiles/universal.gmk Wed Jul 05 20:01:44 2017 +0200
@@ -25,6 +25,8 @@
# macosx universal builds
universal_product:
$(MAKE) MACOSX_UNIVERSAL=true all_product_universal
+universal_optimized:
+ $(MAKE) MACOSX_UNIVERSAL=true all_optimized_universal
universal_fastdebug:
$(MAKE) MACOSX_UNIVERSAL=true all_fastdebug_universal
universal_debug:
@@ -36,6 +38,10 @@
# $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 $(COMMON_VM_PRODUCT_TARGETS)
$(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 $(COMMON_VM_PRODUCT_TARGETS)
$(QUIETLY) $(MAKE) BUILD_FLAVOR=product EXPORT_SUBDIR= universalize
+all_optimized_universal:
+# $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 $(COMMON_VM_OPTIMIZED_TARGETS)
+ $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 $(COMMON_VM_OPTIMIZED_TARGETS)
+ $(QUIETLY) $(MAKE) BUILD_FLAVOR=optimized EXPORT_SUBDIR=/optimized universalize
all_fastdebug_universal:
# $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 $(COMMON_VM_FASTDEBUG_TARGETS)
$(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 $(COMMON_VM_FASTDEBUG_TARGETS)
@@ -98,13 +104,15 @@
export_product_jdk::
$(MAKE) EXPORT_SUBDIR= export_universal
export_optimized_jdk::
- $(MAKE) EXPORT_SUBDIR= export_universal
+ $(MAKE) EXPORT_SUBDIR=/optimized export_universal
export_fastdebug_jdk::
$(MAKE) EXPORT_SUBDIR=/fastdebug export_universal
export_debug_jdk::
$(MAKE) EXPORT_SUBDIR=/debug export_universal
copy_product_jdk::
$(MAKE) COPY_SUBDIR= copy_universal
+copy_optimized_jdk::
+ $(MAKE) COPY_SUBDIR=/optimized copy_universal
copy_fastdebug_jdk::
$(MAKE) COPY_SUBDIR=/fastdebug copy_universal
copy_debug_jdk::
@@ -112,5 +120,6 @@
.PHONY: universal_product universal_fastdebug universal_debug \
all_product_universal all_fastdebug_universal all_debug_universal \
+ universal_optimized all_optimized_universal \
universalize export_universal copy_universal \
$(UNIVERSAL_LIPO_LIST) $(UNIVERSAL_COPY_LIST)
--- a/hotspot/make/linux/Makefile Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/make/linux/Makefile Wed Jul 05 20:01:44 2017 +0200
@@ -256,36 +256,36 @@
$(SUBDIRS_TIERED): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=tiered
+ +$(BUILDTREE) VARIANT=tiered
$(SUBDIRS_C2): $(BUILDTREE_MAKE)
ifeq ($(FORCE_TIERED),1)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
+ +$(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
else
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=compiler2
+ +$(BUILDTREE) VARIANT=compiler2
endif
$(SUBDIRS_C1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=compiler1
+ +$(BUILDTREE) VARIANT=compiler1
$(SUBDIRS_CORE): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=core
+ +$(BUILDTREE) VARIANT=core
$(SUBDIRS_ZERO): $(BUILDTREE_MAKE) platform_zero
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
+ +$(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
$(SUBDIRS_SHARK): $(BUILDTREE_MAKE) platform_zero
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
+ +$(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
$(SUBDIRS_MINIMAL1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=minimal1
+ +$(BUILDTREE) VARIANT=minimal1
platform_zero: $(GAMMADIR)/make/$(OSNAME)/platform_zero.in
@@ -399,3 +399,5 @@
.PHONY: clean clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark docs clean_docs
.PHONY: checks check_os_version check_j2se_version
.PHONY: $(HS_ALT_MAKE)/$(OSNAME)/Makefile.make
+
+.NOTPARALLEL:
--- a/hotspot/make/linux/makefiles/buildtree.make Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/make/linux/makefiles/buildtree.make Wed Jul 05 20:01:44 2017 +0200
@@ -172,7 +172,7 @@
# Run make in each subdirectory recursively.
$(SUBMAKE_DIRS): $(SIMPLE_DIRS) FORCE
$(QUIETLY) [ -d $@ ] || { mkdir -p $@; }
- $(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
+ +$(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
$(QUIETLY) touch $@
$(SIMPLE_DIRS):
@@ -377,3 +377,5 @@
FORCE:
.PHONY: all FORCE
+
+.NOTPARALLEL:
--- a/hotspot/make/linux/makefiles/top.make Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/make/linux/makefiles/top.make Wed Jul 05 20:01:44 2017 +0200
@@ -69,7 +69,13 @@
# Wierd argument adjustment for "gnumake -j..."
adjust-mflags = $(GENERATED)/adjust-mflags
-MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
+# If SPEC is set, it's from configure and it's already controlling concurrency
+# for us. Skip setting -j with HOTSPOT_BUILD_JOBS.
+ifeq ($(SPEC), )
+ MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
+else
+ MFLAGS-adjusted = -r $(MFLAGS)
+endif
# default target: update lists, make vm
@@ -119,7 +125,7 @@
@+mv $@+ $@
the_vm: vm_build_preliminaries $(adjust-mflags)
- @$(UpdatePCH)
+ +@$(UpdatePCH)
@$(MAKE) -f vm.make $(MFLAGS-adjusted)
install: the_vm
@@ -128,7 +134,7 @@
# next rules support "make foo.[ois]"
%.o %.i %.s:
- $(UpdatePCH)
+ +$(UpdatePCH)
$(MAKE) -f vm.make $(MFLAGS) $@
#$(MAKE) -f vm.make $@
@@ -145,3 +151,5 @@
.PHONY: default vm_build_preliminaries
.PHONY: lists ad_stuff jvmti_stuff sa_stuff the_vm clean realclean
.PHONY: checks check_os_version install
+
+.NOTPARALLEL:
--- a/hotspot/make/solaris/Makefile Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/make/solaris/Makefile Wed Jul 05 20:01:44 2017 +0200
@@ -200,24 +200,24 @@
$(SUBDIRS_TIERED): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=tiered
+ +$(BUILDTREE) VARIANT=tiered
$(SUBDIRS_C2): $(BUILDTREE_MAKE)
ifeq ($(FORCE_TIERED),1)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
+ +$(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
else
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=compiler2
+ +$(BUILDTREE) VARIANT=compiler2
endif
$(SUBDIRS_C1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=compiler1
+ +$(BUILDTREE) VARIANT=compiler1
$(SUBDIRS_CORE): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=core
+ +$(BUILDTREE) VARIANT=core
# Define INSTALL=y at command line to automatically copy JVM into JAVA_HOME
@@ -292,3 +292,5 @@
.PHONY: all compiler1 compiler2 core
.PHONY: clean clean_compiler1 clean_compiler2 clean_core docs clean_docs
.PHONY: checks check_os_version check_j2se_version
+
+.NOTPARALLEL:
--- a/hotspot/make/solaris/makefiles/buildtree.make Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/make/solaris/makefiles/buildtree.make Wed Jul 05 20:01:44 2017 +0200
@@ -165,7 +165,7 @@
# Run make in each subdirectory recursively.
$(SUBMAKE_DIRS): $(SIMPLE_DIRS) FORCE
$(QUIETLY) [ -d $@ ] || { mkdir -p $@; }
- $(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
+ +$(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
$(QUIETLY) touch $@
$(SIMPLE_DIRS):
@@ -364,3 +364,5 @@
FORCE:
.PHONY: all FORCE
+
+.NOTPARALLEL:
--- a/hotspot/make/solaris/makefiles/top.make Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/make/solaris/makefiles/top.make Wed Jul 05 20:01:44 2017 +0200
@@ -62,7 +62,13 @@
# Wierd argument adjustment for "gnumake -j..."
adjust-mflags = $(GENERATED)/adjust-mflags
-MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
+# If SPEC is set, it's from configure and it's already controlling concurrency
+# for us. Skip setting -j with HOTSPOT_BUILD_JOBS.
+ifeq ($(SPEC), )
+ MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
+else
+ MFLAGS-adjusted = -r $(MFLAGS)
+endif
# default target: update lists, make vm
@@ -136,3 +142,5 @@
.PHONY: default vm_build_preliminaries
.PHONY: lists ad_stuff jvmti_stuff trace_stuff sa_stuff the_vm clean realclean
.PHONY: checks check_os_version install
+
+.NOTPARALLEL:
--- a/hotspot/make/solaris/makefiles/vm.make Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/make/solaris/makefiles/vm.make Wed Jul 05 20:01:44 2017 +0200
@@ -143,7 +143,7 @@
LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle
endif # sparcWorks
-LIBS += -lkstat
+LIBS += -lkstat -lpicl
# By default, link the *.o into the library, not the executable.
LINK_INTO$(LINK_INTO) = LIBJVM
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -32,6 +32,7 @@
int VM_Version::_features = VM_Version::unknown_m;
const char* VM_Version::_features_str = "";
+unsigned int VM_Version::_L2_cache_line_size = 0;
void VM_Version::initialize() {
_features = determine_features();
@@ -192,7 +193,7 @@
}
assert(BlockZeroingLowLimit > 0, "invalid value");
- if (has_block_zeroing()) {
+ if (has_block_zeroing() && cache_line_size > 0) {
if (FLAG_IS_DEFAULT(UseBlockZeroing)) {
FLAG_SET_DEFAULT(UseBlockZeroing, true);
}
@@ -202,7 +203,7 @@
}
assert(BlockCopyLowLimit > 0, "invalid value");
- if (has_block_zeroing()) { // has_blk_init() && is_T4(): core's local L2 cache
+ if (has_block_zeroing() && cache_line_size > 0) { // has_blk_init() && is_T4(): core's local L2 cache
if (FLAG_IS_DEFAULT(UseBlockCopy)) {
FLAG_SET_DEFAULT(UseBlockCopy, true);
}
@@ -252,49 +253,6 @@
// buf is started with ", " or is empty
_features_str = os::strdup(strlen(buf) > 2 ? buf + 2 : buf);
- // There are three 64-bit SPARC families that do not overlap, e.g.,
- // both is_ultra3() and is_sparc64() cannot be true at the same time.
- // Within these families, there can be more than one chip, e.g.,
- // is_T4() and is_T7() machines are also is_niagara().
- if (is_ultra3()) {
- assert(_L1_data_cache_line_size == 0, "overlap with Ultra3 family");
- // Ref: UltraSPARC III Cu Processor
- _L1_data_cache_line_size = 64;
- }
- if (is_niagara()) {
- assert(_L1_data_cache_line_size == 0, "overlap with niagara family");
- // All Niagara's are sun4v's, but not all sun4v's are Niagaras, e.g.,
- // Fujitsu SPARC64 is sun4v, but we don't want it in this block.
- //
- // Ref: UltraSPARC T1 Supplement to the UltraSPARC Architecture 2005
- // Appendix F.1.3.1 Cacheable Accesses
- // -> 16-byte L1 cache line size
- //
- // Ref: UltraSPARC T2: A Highly-Threaded, Power-Efficient, SPARC SOC
- // Section III: SPARC Processor Core
- // -> 16-byte L1 cache line size
- //
- // Ref: Oracle's SPARC T4-1, SPARC T4-2, SPARC T4-4, and SPARC T4-1B Server Architecture
- // Section SPARC T4 Processor Cache Architecture
- // -> 32-byte L1 cache line size (no longer see that info on this ref)
- //
- // XXX - still need a T7 reference here
- //
- if (is_T7()) { // T7 or newer
- _L1_data_cache_line_size = 64;
- } else if (is_T4()) { // T4 or newer (until T7)
- _L1_data_cache_line_size = 32;
- } else { // T1 or newer (until T4)
- _L1_data_cache_line_size = 16;
- }
- }
- if (is_sparc64()) {
- guarantee(_L1_data_cache_line_size == 0, "overlap with SPARC64 family");
- // Ref: Fujitsu SPARC64 VII Processor
- // Section 4 Cache System
- _L1_data_cache_line_size = 64;
- }
-
// UseVIS is set to the smallest of what hardware supports and what
// the command line requires. I.e., you cannot set UseVIS to 3 on
// older UltraSparc which do not support it.
@@ -401,6 +359,7 @@
#ifndef PRODUCT
if (PrintMiscellaneous && Verbose) {
tty->print_cr("L1 data cache line size: %u", L1_data_cache_line_size());
+ tty->print_cr("L2 cache line size: %u", L2_cache_line_size());
tty->print("Allocation");
if (AllocatePrefetchStyle <= 0) {
tty->print_cr(": no prefetching");
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp Wed Jul 05 20:01:44 2017 +0200
@@ -96,6 +96,9 @@
static int _features;
static const char* _features_str;
+ static unsigned int _L2_cache_line_size;
+ static unsigned int L2_cache_line_size() { return _L2_cache_line_size; }
+
static void print_features();
static int determine_features();
static int platform_features(int features);
@@ -167,9 +170,8 @@
static const char* cpu_features() { return _features_str; }
- static intx prefetch_data_size() {
- return is_T4() && !is_T7() ? 32 : 64; // default prefetch block size on sparc
- }
+ // default prefetch block size on sparc
+ static intx prefetch_data_size() { return L2_cache_line_size(); }
// Prefetch
static intx prefetch_copy_interval_in_bytes() {
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Wed Jul 05 20:01:44 2017 +0200
@@ -26,6 +26,7 @@
#define CPU_X86_VM_ASSEMBLER_X86_HPP
#include "asm/register.hpp"
+#include "vm_version_x86.hpp"
class BiasedLockingCounters;
@@ -1292,14 +1293,34 @@
if (order_constraint & StoreLoad) {
// All usable chips support "locked" instructions which suffice
// as barriers, and are much faster than the alternative of
- // using cpuid instruction. We use here a locked add [esp],0.
+ // using cpuid instruction. We use here a locked add [esp-C],0.
// This is conveniently otherwise a no-op except for blowing
- // flags.
+ // flags, and introducing a false dependency on target memory
+ // location. We can't do anything with flags, but we can avoid
+ // memory dependencies in the current method by locked-adding
+ // somewhere else on the stack. Doing [esp+C] will collide with
+ // something on stack in current method, hence we go for [esp-C].
+ // It is convenient since it is almost always in data cache, for
+ // any small C. We need to step back from SP to avoid data
+ // dependencies with other things on below SP (callee-saves, for
+ // example). Without a clear way to figure out the minimal safe
+ // distance from SP, it makes sense to step back the complete
+ // cache line, as this will also avoid possible second-order effects
+ // with locked ops against the cache line. Our choice of offset
+ // is bounded by x86 operand encoding, which should stay within
+ // [-128; +127] to have the 8-byte displacement encoding.
+ //
// Any change to this code may need to revisit other places in
// the code where this idiom is used, in particular the
// orderAccess code.
+
+ int offset = -VM_Version::L1_line_size();
+ if (offset < -128) {
+ offset = -128;
+ }
+
lock();
- addl(Address(rsp, 0), 0);// Assert the lock# signal here
+ addl(Address(rsp, offset), 0);// Assert the lock# signal here
}
}
}
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -820,14 +820,10 @@
}
address InterpreterGenerator::generate_native_entry(bool synchronized) {
- assert(synchronized == false, "should be");
-
return generate_entry((address) CppInterpreter::native_entry);
}
address InterpreterGenerator::generate_normal_entry(bool synchronized) {
- assert(synchronized == false, "should be");
-
return generate_entry((address) CppInterpreter::normal_entry);
}
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -1644,8 +1644,20 @@
return true;
}
+int _print_dll_info_cb(const char * name, address base_address, address top_address, void * param) {
+ outputStream * out = (outputStream *) param;
+ out->print_cr(PTR_FORMAT " \t%s", base_address, name);
+ return 0;
+}
+
void os::print_dll_info(outputStream *st) {
st->print_cr("Dynamic libraries:");
+ if (get_loaded_modules_info(_print_dll_info_cb, (void *)st)) {
+ st->print_cr("Error: Cannot print dynamic libraries.");
+ }
+}
+
+int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
#ifdef RTLD_DI_LINKMAP
Dl_info dli;
void *handle;
@@ -1654,36 +1666,41 @@
if (dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli) == 0 ||
dli.dli_fname == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
+ return 1;
}
handle = dlopen(dli.dli_fname, RTLD_LAZY);
if (handle == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
+ return 1;
}
dlinfo(handle, RTLD_DI_LINKMAP, &map);
if (map == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
+ dlclose(handle);
+ return 1;
}
while (map->l_prev != NULL)
map = map->l_prev;
while (map != NULL) {
- st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name);
+ // Value for top_address is returned as 0 since we don't have any information about module size
+ if (callback(map->l_name, (address)map->l_addr, (address)0, param)) {
+ dlclose(handle);
+ return 1;
+ }
map = map->l_next;
}
dlclose(handle);
#elif defined(__APPLE__)
for (uint32_t i = 1; i < _dyld_image_count(); i++) {
- st->print_cr(PTR_FORMAT " \t%s", _dyld_get_image_header(i),
- _dyld_get_image_name(i));
+ // Value for top_address is returned as 0 since we don't have any information about module size
+ if (callback(_dyld_get_image_name(i), (address)_dyld_get_image_header(i), (address)0, param)) {
+ return 1;
+ }
}
+ return 0;
#else
- st->print_cr("Error: Cannot print dynamic libraries.");
+ return 1;
#endif
}
--- a/hotspot/src/os/linux/vm/os_linux.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -2120,6 +2120,40 @@
}
}
+int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
+ FILE *procmapsFile = NULL;
+
+ // Open the procfs maps file for the current process
+ if ((procmapsFile = fopen("/proc/self/maps", "r")) != NULL) {
+ // Allocate PATH_MAX for file name plus a reasonable size for other fields.
+ char line[PATH_MAX + 100];
+
+ // Read line by line from 'file'
+ while (fgets(line, sizeof(line), procmapsFile) != NULL) {
+ u8 base, top, offset, inode;
+ char permissions[5];
+ char device[6];
+ char name[PATH_MAX + 1];
+
+ // Parse fields from line
+ sscanf(line, "%lx-%lx %4s %lx %5s %ld %s", &base, &top, permissions, &offset, device, &inode, name);
+
+ // Filter by device id '00:00' so that we only get file system mapped files.
+ if (strcmp(device, "00:00") != 0) {
+
+ // Call callback with the fields of interest
+ if(callback(name, (address)base, (address)top, param)) {
+ // Oops abort, callback aborted
+ fclose(procmapsFile);
+ return 1;
+ }
+ }
+ }
+ fclose(procmapsFile);
+ }
+ return 0;
+}
+
void os::print_os_info_brief(outputStream* st) {
os::Linux::print_distro_info(st);
--- a/hotspot/src/os/posix/vm/os_posix.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/os/posix/vm/os_posix.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -215,6 +215,9 @@
struct utsname name;
uname(&name);
st->print("%s ", name.sysname);
+#ifdef ASSERT
+ st->print("%s ", name.nodename);
+#endif
st->print("%s ", name.release);
st->print("%s ", name.version);
st->print("%s", name.machine);
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -1722,41 +1722,54 @@
return false;
}
-// Prints the names and full paths of all opened dynamic libraries
-// for current process
-void os::print_dll_info(outputStream * st) {
+int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
Dl_info dli;
- void *handle;
+ // Sanity check?
+ if (dladdr(CAST_FROM_FN_PTR(void *, os::get_loaded_modules_info), &dli) == 0 ||
+ dli.dli_fname == NULL) {
+ return 1;
+ }
+
+ void * handle = dlopen(dli.dli_fname, RTLD_LAZY);
+ if (handle == NULL) {
+ return 1;
+ }
+
Link_map *map;
- Link_map *p;
-
- st->print_cr("Dynamic libraries:"); st->flush();
-
- if (dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli) == 0 ||
- dli.dli_fname == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
- }
- handle = dlopen(dli.dli_fname, RTLD_LAZY);
- if (handle == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
- }
dlinfo(handle, RTLD_DI_LINKMAP, &map);
if (map == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
- }
-
- while (map->l_prev != NULL)
+ dlclose(handle);
+ return 1;
+ }
+
+ while (map->l_prev != NULL) {
map = map->l_prev;
+ }
while (map != NULL) {
- st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name);
+ // Iterate through all map entries and call callback with fields of interest
+ if(callback(map->l_name, (address)map->l_addr, (address)0, param)) {
+ dlclose(handle);
+ return 1;
+ }
map = map->l_next;
}
dlclose(handle);
+ return 0;
+}
+
+int _print_dll_info_cb(const char * name, address base_address, address top_address, void * param) {
+ outputStream * out = (outputStream *) param;
+ out->print_cr(PTR_FORMAT " \t%s", base_address, name);
+ return 0;
+}
+
+void os::print_dll_info(outputStream * st) {
+ st->print_cr("Dynamic libraries:"); st->flush();
+ if (get_loaded_modules_info(_print_dll_info_cb, (void *)st)) {
+ st->print_cr("Error: Cannot print dynamic libraries.");
+ }
}
// Loads .dll/.so and
--- a/hotspot/src/os/windows/vm/os_windows.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -1301,120 +1301,6 @@
}
#endif
-
-// Enumerate all modules for a given process ID
-//
-// Notice that Windows 95/98/Me and Windows NT/2000/XP have
-// different API for doing this. We use PSAPI.DLL on NT based
-// Windows and ToolHelp on 95/98/Me.
-
-// Callback function that is called by enumerate_modules() on
-// every DLL module.
-// Input parameters:
-// int pid,
-// char* module_file_name,
-// address module_base_addr,
-// unsigned module_size,
-// void* param
-typedef int (*EnumModulesCallbackFunc)(int, char *, address, unsigned, void *);
-
-// enumerate_modules for Windows NT, using PSAPI
-static int _enumerate_modules_winnt( int pid, EnumModulesCallbackFunc func, void * param)
-{
- HANDLE hProcess;
-
-# define MAX_NUM_MODULES 128
- HMODULE modules[MAX_NUM_MODULES];
- static char filename[MAX_PATH];
- int result = 0;
-
- if (!os::PSApiDll::PSApiAvailable()) {
- return 0;
- }
-
- hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
- FALSE, pid);
- if (hProcess == NULL) return 0;
-
- DWORD size_needed;
- if (!os::PSApiDll::EnumProcessModules(hProcess, modules,
- sizeof(modules), &size_needed)) {
- CloseHandle(hProcess);
- return 0;
- }
-
- // number of modules that are currently loaded
- int num_modules = size_needed / sizeof(HMODULE);
-
- for (int i = 0; i < MIN2(num_modules, MAX_NUM_MODULES); i++) {
- // Get Full pathname:
- if (!os::PSApiDll::GetModuleFileNameEx(hProcess, modules[i],
- filename, sizeof(filename))) {
- filename[0] = '\0';
- }
-
- MODULEINFO modinfo;
- if (!os::PSApiDll::GetModuleInformation(hProcess, modules[i],
- &modinfo, sizeof(modinfo))) {
- modinfo.lpBaseOfDll = NULL;
- modinfo.SizeOfImage = 0;
- }
-
- // Invoke callback function
- result = func(pid, filename, (address)modinfo.lpBaseOfDll,
- modinfo.SizeOfImage, param);
- if (result) break;
- }
-
- CloseHandle(hProcess);
- return result;
-}
-
-
-// enumerate_modules for Windows 95/98/ME, using TOOLHELP
-static int _enumerate_modules_windows( int pid, EnumModulesCallbackFunc func, void *param)
-{
- HANDLE hSnapShot;
- static MODULEENTRY32 modentry;
- int result = 0;
-
- if (!os::Kernel32Dll::HelpToolsAvailable()) {
- return 0;
- }
-
- // Get a handle to a Toolhelp snapshot of the system
- hSnapShot = os::Kernel32Dll::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
- if (hSnapShot == INVALID_HANDLE_VALUE) {
- return FALSE;
- }
-
- // iterate through all modules
- modentry.dwSize = sizeof(MODULEENTRY32);
- bool not_done = os::Kernel32Dll::Module32First( hSnapShot, &modentry ) != 0;
-
- while (not_done) {
- // invoke the callback
- result=func(pid, modentry.szExePath, (address)modentry.modBaseAddr,
- modentry.modBaseSize, param);
- if (result) break;
-
- modentry.dwSize = sizeof(MODULEENTRY32);
- not_done = os::Kernel32Dll::Module32Next( hSnapShot, &modentry ) != 0;
- }
-
- CloseHandle(hSnapShot);
- return result;
-}
-
-int enumerate_modules( int pid, EnumModulesCallbackFunc func, void * param )
-{
- // Get current process ID if caller doesn't provide it.
- if (!pid) pid = os::current_process_id();
-
- if (os::win32::is_nt()) return _enumerate_modules_winnt (pid, func, param);
- else return _enumerate_modules_windows(pid, func, param);
-}
-
struct _modinfo {
address addr;
char* full_path; // point to a char buffer
@@ -1422,13 +1308,13 @@
address base_addr;
};
-static int _locate_module_by_addr(int pid, char * mod_fname, address base_addr,
- unsigned size, void * param) {
+static int _locate_module_by_addr(const char * mod_fname, address base_addr,
+ address top_address, void * param) {
struct _modinfo *pmod = (struct _modinfo *)param;
if (!pmod) return -1;
- if (base_addr <= pmod->addr &&
- base_addr+size > pmod->addr) {
+ if (base_addr <= pmod->addr &&
+ top_address > pmod->addr) {
// if a buffer is provided, copy path name to the buffer
if (pmod->full_path) {
jio_snprintf(pmod->full_path, pmod->buflen, "%s", mod_fname);
@@ -1453,8 +1339,7 @@
mi.addr = addr;
mi.full_path = buf;
mi.buflen = buflen;
- int pid = os::current_process_id();
- if (enumerate_modules(pid, _locate_module_by_addr, (void *)&mi)) {
+ if (get_loaded_modules_info(_locate_module_by_addr, (void *)&mi)) {
// buf already contains path name
if (offset) *offset = addr - mi.base_addr;
return true;
@@ -1479,14 +1364,14 @@
}
// save the start and end address of jvm.dll into param[0] and param[1]
-static int _locate_jvm_dll(int pid, char* mod_fname, address base_addr,
- unsigned size, void * param) {
+static int _locate_jvm_dll(const char* mod_fname, address base_addr,
+ address top_address, void * param) {
if (!param) return -1;
- if (base_addr <= (address)_locate_jvm_dll &&
- base_addr+size > (address)_locate_jvm_dll) {
+ if (base_addr <= (address)_locate_jvm_dll &&
+ top_address > (address)_locate_jvm_dll) {
((address*)param)[0] = base_addr;
- ((address*)param)[1] = base_addr + size;
+ ((address*)param)[1] = top_address;
return 1;
}
return 0;
@@ -1497,8 +1382,7 @@
// check if addr is inside jvm.dll
bool os::address_is_in_vm(address addr) {
if (!vm_lib_location[0] || !vm_lib_location[1]) {
- int pid = os::current_process_id();
- if (!enumerate_modules(pid, _locate_jvm_dll, (void *)vm_lib_location)) {
+ if (!get_loaded_modules_info(_locate_jvm_dll, (void *)vm_lib_location)) {
assert(false, "Can't find jvm module.");
return false;
}
@@ -1508,14 +1392,13 @@
}
// print module info; param is outputStream*
-static int _print_module(int pid, char* fname, address base,
- unsigned size, void* param) {
+static int _print_module(const char* fname, address base_address,
+ address top_address, void* param) {
if (!param) return -1;
outputStream* st = (outputStream*)param;
- address end_addr = base + size;
- st->print(PTR_FORMAT " - " PTR_FORMAT " \t%s\n", base, end_addr, fname);
+ st->print(PTR_FORMAT " - " PTR_FORMAT " \t%s\n", base_address, top_address, fname);
return 0;
}
@@ -1644,11 +1527,60 @@
return NULL;
}
-
void os::print_dll_info(outputStream *st) {
- int pid = os::current_process_id();
st->print_cr("Dynamic libraries:");
- enumerate_modules(pid, _print_module, (void *)st);
+ get_loaded_modules_info(_print_module, (void *)st);
+}
+
+int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
+ HANDLE hProcess;
+
+# define MAX_NUM_MODULES 128
+ HMODULE modules[MAX_NUM_MODULES];
+ static char filename[MAX_PATH];
+ int result = 0;
+
+ if (!os::PSApiDll::PSApiAvailable()) {
+ return 0;
+ }
+
+ int pid = os::current_process_id();
+ hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
+ FALSE, pid);
+ if (hProcess == NULL) return 0;
+
+ DWORD size_needed;
+ if (!os::PSApiDll::EnumProcessModules(hProcess, modules,
+ sizeof(modules), &size_needed)) {
+ CloseHandle(hProcess);
+ return 0;
+ }
+
+ // number of modules that are currently loaded
+ int num_modules = size_needed / sizeof(HMODULE);
+
+ for (int i = 0; i < MIN2(num_modules, MAX_NUM_MODULES); i++) {
+ // Get Full pathname:
+ if (!os::PSApiDll::GetModuleFileNameEx(hProcess, modules[i],
+ filename, sizeof(filename))) {
+ filename[0] = '\0';
+ }
+
+ MODULEINFO modinfo;
+ if (!os::PSApiDll::GetModuleInformation(hProcess, modules[i],
+ &modinfo, sizeof(modinfo))) {
+ modinfo.lpBaseOfDll = NULL;
+ modinfo.SizeOfImage = 0;
+ }
+
+ // Invoke callback function
+ result = callback(filename, (address)modinfo.lpBaseOfDll,
+ (address)((u8)modinfo.lpBaseOfDll + (u8)modinfo.SizeOfImage), param);
+ if (result) break;
+ }
+
+ CloseHandle(hProcess);
+ return result;
}
void os::print_os_info_brief(outputStream* st) {
@@ -1656,8 +1588,17 @@
}
void os::print_os_info(outputStream* st) {
- st->print("OS:");
-
+#ifdef ASSERT
+ char buffer[1024];
+ DWORD size = sizeof(buffer);
+ st->print(" HostName: ");
+ if (GetComputerNameEx(ComputerNameDnsHostname, buffer, &size)) {
+ st->print("%s", buffer);
+ } else {
+ st->print("N/A");
+ }
+#endif
+ st->print(" OS:");
os::win32::print_windows_version(st);
}
--- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -563,3 +563,8 @@
assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
}
#endif
+
+int os::extra_bang_size_in_bytes() {
+ // PPC does not require the additional stack bang.
+ return 0;
+}
--- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -1030,3 +1030,8 @@
void os::verify_stack_alignment() {
}
#endif
+
+int os::extra_bang_size_in_bytes() {
+ // JDK-8050147 requires the full cache line bang for x86.
+ return VM_Version::L1_line_size();
+}
--- a/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -465,3 +465,8 @@
void os::verify_stack_alignment() {
}
#endif
+
+int os::extra_bang_size_in_bytes() {
+ // Zero does not require an additional stack bang.
+ return 0;
+}
--- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -612,3 +612,8 @@
assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
}
#endif
+
+int os::extra_bang_size_in_bytes() {
+ // PPC does not require the additional stack bang.
+ return 0;
+}
--- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -752,3 +752,8 @@
void os::verify_stack_alignment() {
}
#endif
+
+int os::extra_bang_size_in_bytes() {
+ // SPARC does not require the additional stack bang.
+ return 0;
+}
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -930,3 +930,8 @@
// keep the page mapped so CS limit isn't reduced.
#endif
}
+
+int os::extra_bang_size_in_bytes() {
+ // JDK-8050147 requires the full cache line bang for x86.
+ return VM_Version::L1_line_size();
+}
--- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -495,3 +495,8 @@
void os::verify_stack_alignment() {
}
#endif
+
+int os::extra_bang_size_in_bytes() {
+ // Zero does not require an additional stack banging.
+ return 0;
+}
--- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -774,3 +774,8 @@
void os::verify_stack_alignment() {
}
#endif
+
+int os::extra_bang_size_in_bytes() {
+ // SPARC does not require an additional stack bang.
+ return 0;
+}
--- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -28,10 +28,140 @@
#include "runtime/os.hpp"
#include "vm_version_sparc.hpp"
-# include <sys/auxv.h>
-# include <sys/auxv_SPARC.h>
-# include <sys/systeminfo.h>
-# include <kstat.h>
+#include <sys/auxv.h>
+#include <sys/auxv_SPARC.h>
+#include <sys/systeminfo.h>
+#include <kstat.h>
+#include <picl.h>
+
+extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result);
+extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result);
+
+class PICL {
+ // Get a value of the integer property. The value in the tree can be either 32 or 64 bit
+ // depending on the platform. The result is converted to int.
+ static int get_int_property(picl_nodehdl_t nodeh, const char* name, int* result) {
+ picl_propinfo_t pinfo;
+ picl_prophdl_t proph;
+ if (picl_get_prop_by_name(nodeh, name, &proph) != PICL_SUCCESS ||
+ picl_get_propinfo(proph, &pinfo) != PICL_SUCCESS) {
+ return PICL_FAILURE;
+ }
+
+ if (pinfo.type != PICL_PTYPE_INT && pinfo.type != PICL_PTYPE_UNSIGNED_INT) {
+ assert(false, "Invalid property type");
+ return PICL_FAILURE;
+ }
+ if (pinfo.size == sizeof(int64_t)) {
+ int64_t val;
+ if (picl_get_propval(proph, &val, sizeof(int64_t)) != PICL_SUCCESS) {
+ return PICL_FAILURE;
+ }
+ *result = static_cast<int>(val);
+ } else if (pinfo.size == sizeof(int32_t)) {
+ int32_t val;
+ if (picl_get_propval(proph, &val, sizeof(int32_t)) != PICL_SUCCESS) {
+ return PICL_FAILURE;
+ }
+ *result = static_cast<int>(val);
+ } else {
+ assert(false, "Unexpected integer property size");
+ return PICL_FAILURE;
+ }
+ return PICL_SUCCESS;
+ }
+
+ // Visitor and a state machine that visits integer properties and verifies that the
+ // values are the same. Stores the unique value observed.
+ class UniqueValueVisitor {
+ enum {
+ INITIAL, // Start state, no assignments happened
+ ASSIGNED, // Assigned a value
+ INCONSISTENT // Inconsistent value seen
+ } _state;
+ int _value;
+ public:
+ UniqueValueVisitor() : _state(INITIAL) { }
+ int value() {
+ assert(_state == ASSIGNED, "Precondition");
+ return _value;
+ }
+ void set_value(int value) {
+ assert(_state == INITIAL, "Precondition");
+ _value = value;
+ _state = ASSIGNED;
+ }
+ bool is_initial() { return _state == INITIAL; }
+ bool is_assigned() { return _state == ASSIGNED; }
+ bool is_inconsistent() { return _state == INCONSISTENT; }
+ void set_inconsistent() { _state = INCONSISTENT; }
+
+ static int visit(picl_nodehdl_t nodeh, const char* name, void *arg) {
+ UniqueValueVisitor *state = static_cast<UniqueValueVisitor*>(arg);
+ assert(!state->is_inconsistent(), "Precondition");
+ int curr;
+ if (PICL::get_int_property(nodeh, name, &curr) == PICL_SUCCESS) {
+ if (!state->is_assigned()) { // first iteration
+ state->set_value(curr);
+ } else if (curr != state->value()) { // following iterations
+ state->set_inconsistent();
+ }
+ }
+ if (state->is_inconsistent()) {
+ return PICL_WALK_TERMINATE;
+ }
+ return PICL_WALK_CONTINUE;
+ }
+ };
+
+ int _L1_data_cache_line_size;
+ int _L2_cache_line_size;
+public:
+ static int get_l1_data_cache_line_size(picl_nodehdl_t nodeh, void *state) {
+ return UniqueValueVisitor::visit(nodeh, "l1-dcache-line-size", state);
+ }
+ static int get_l2_cache_line_size(picl_nodehdl_t nodeh, void *state) {
+ return UniqueValueVisitor::visit(nodeh, "l2-cache-line-size", state);
+ }
+
+ PICL() : _L1_data_cache_line_size(0), _L2_cache_line_size(0) {
+ if (picl_initialize() == PICL_SUCCESS) {
+ picl_nodehdl_t rooth;
+ if (picl_get_root(&rooth) == PICL_SUCCESS) {
+ UniqueValueVisitor L1_state;
+ // Visit all "cpu" class instances
+ picl_walk_tree_by_class(rooth, "cpu", &L1_state, PICL_get_l1_data_cache_line_size_helper);
+ if (L1_state.is_initial()) { // Still initial, iteration found no values
+ // Try walk all "core" class instances, it might be a Fujitsu machine
+ picl_walk_tree_by_class(rooth, "core", &L1_state, PICL_get_l1_data_cache_line_size_helper);
+ }
+ if (L1_state.is_assigned()) { // Is there a value?
+ _L1_data_cache_line_size = L1_state.value();
+ }
+
+ UniqueValueVisitor L2_state;
+ picl_walk_tree_by_class(rooth, "cpu", &L2_state, PICL_get_l2_cache_line_size_helper);
+ if (L2_state.is_initial()) {
+ picl_walk_tree_by_class(rooth, "core", &L2_state, PICL_get_l2_cache_line_size_helper);
+ }
+ if (L2_state.is_assigned()) {
+ _L2_cache_line_size = L2_state.value();
+ }
+ }
+ picl_shutdown();
+ }
+ }
+
+ unsigned int L1_data_cache_line_size() const { return _L1_data_cache_line_size; }
+ unsigned int L2_cache_line_size() const { return _L2_cache_line_size; }
+};
+
+extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) {
+ return PICL::get_l1_data_cache_line_size(nodeh, result);
+}
+extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) {
+ return PICL::get_l2_cache_line_size(nodeh, result);
+}
// We need to keep these here as long as we have to build on Solaris
// versions before 10.
@@ -211,5 +341,10 @@
kstat_close(kc);
}
+ // Figure out cache line sizes using PICL
+ PICL picl;
+ _L1_data_cache_line_size = picl.L1_data_cache_line_size();
+ _L2_cache_line_size = picl.L2_cache_line_size();
+
return features;
}
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -918,3 +918,8 @@
#endif
}
#endif
+
+int os::extra_bang_size_in_bytes() {
+ // JDK-8050147 requires the full cache line bang for x86.
+ return VM_Version::L1_line_size();
+}
--- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -639,3 +639,8 @@
#endif
}
#endif
+
+int os::extra_bang_size_in_bytes() {
+ // JDK-8050147 requires the full cache line bang for x86.
+ return VM_Version::L1_line_size();
+}
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -170,7 +170,7 @@
// removes the need to bang the stack in the deoptimization blob which
// in turn simplifies stack overflow handling.
int LIR_Assembler::bang_size_in_bytes() const {
- return MAX2(initial_frame_size_in_bytes(), _compilation->interpreter_frame_size());
+ return MAX2(initial_frame_size_in_bytes() + os::extra_bang_size_in_bytes(), _compilation->interpreter_frame_size());
}
void LIR_Assembler::emit_exception_entries(ExceptionInfoList* info_list) {
--- a/hotspot/src/share/vm/ci/ciEnv.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -926,7 +926,7 @@
#ifdef ASSERT
if (!counter_changed && !PrintCompilation) {
// Print out the compile task that failed
- _task->print_line();
+ _task->print_tty();
}
#endif
assert(counter_changed, "failed dependencies, but counter didn't change");
--- a/hotspot/src/share/vm/classfile/classLoader.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -1528,7 +1528,7 @@
if (TieredCompilation && TieredStopAtLevel >= CompLevel_full_optimization) {
// Clobber the first compile and force second tier compilation
nmethod* nm = m->code();
- if (nm != NULL) {
+ if (nm != NULL && !m->is_method_handle_intrinsic()) {
// Throw out the code so that the code cache doesn't fill up
nm->make_not_entrant();
m->clear_code();
@@ -1547,7 +1547,7 @@
}
nmethod* nm = m->code();
- if (nm != NULL) {
+ if (nm != NULL && !m->is_method_handle_intrinsic()) {
// Throw out the code so that the code cache doesn't fill up
nm->make_not_entrant();
m->clear_code();
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -746,7 +746,7 @@
// mark metadata seen on the stack and code cache so we can delete
// unneeded entries.
bool has_redefined_a_class = JvmtiExport::has_redefined_a_class();
- MetadataOnStackMark md_on_stack;
+ MetadataOnStackMark md_on_stack(has_redefined_a_class);
if (has_redefined_a_class) {
// purge_previous_versions also cleans weak method links. Because
// one method's MDO can reference another method from another
--- a/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -41,7 +41,7 @@
// Walk metadata on the stack and mark it so that redefinition doesn't delete
// it. Class unloading also walks the previous versions and might try to
// delete it, so this class is used by class unloading also.
-MetadataOnStackMark::MetadataOnStackMark() {
+MetadataOnStackMark::MetadataOnStackMark(bool has_redefined_a_class) {
assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
NOT_PRODUCT(_is_active = true;)
if (_marked_objects == NULL) {
@@ -49,7 +49,7 @@
}
Threads::metadata_do(Metadata::mark_on_stack);
- if (JvmtiExport::has_redefined_a_class()) {
+ if (has_redefined_a_class) {
CodeCache::alive_nmethods_do(nmethod::mark_on_stack);
}
CompileBroker::mark_on_stack();
--- a/hotspot/src/share/vm/classfile/metadataOnStackMark.hpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/classfile/metadataOnStackMark.hpp Wed Jul 05 20:01:44 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,7 +37,7 @@
class MetadataOnStackMark : public StackObj {
NOT_PRODUCT(static bool _is_active;)
public:
- MetadataOnStackMark();
+ MetadataOnStackMark(bool has_redefined_a_class);
~MetadataOnStackMark();
static void record(Metadata* m);
};
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -52,6 +52,7 @@
#include "oops/typeArrayKlass.hpp"
#include "prims/jvmtiEnvBase.hpp"
#include "prims/methodHandles.hpp"
+#include "runtime/arguments.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/fieldType.hpp"
#include "runtime/handles.inline.hpp"
@@ -2274,7 +2275,11 @@
m = Method::make_method_handle_intrinsic(iid, signature, CHECK_(empty));
CompileBroker::compile_method(m, InvocationEntryBci, CompLevel_highest_tier,
methodHandle(), CompileThreshold, "MH", CHECK_(empty));
-
+ // Check if we need to have compiled code but we don't.
+ if (!Arguments::is_interpreter_only() && !m->has_compiled_code()) {
+ THROW_MSG_(vmSymbols::java_lang_VirtualMachineError(),
+ "out of space in CodeCache for method handle intrinsic", empty);
+ }
// Now grab the lock. We might have to throw away the new method,
// if a racing thread has managed to install one at the same time.
{
@@ -2288,6 +2293,9 @@
}
assert(spe != NULL && spe->method() != NULL, "");
+ assert(Arguments::is_interpreter_only() || (spe->method()->has_compiled_code() &&
+ spe->method()->code()->entry_point() == spe->method()->from_compiled_entry()),
+ "MH intrinsic invariant");
return spe->method();
}
--- a/hotspot/src/share/vm/code/codeCache.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/code/codeCache.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -249,6 +249,7 @@
#define FOR_ALL_BLOBS(var) for (CodeBlob *var = first() ; var != NULL; var = next(var) )
#define FOR_ALL_ALIVE_BLOBS(var) for (CodeBlob *var = alive(first()); var != NULL; var = alive(next(var)))
#define FOR_ALL_ALIVE_NMETHODS(var) for (nmethod *var = alive_nmethod(first()); var != NULL; var = alive_nmethod(next(var)))
+#define FOR_ALL_NMETHODS(var) for (nmethod *var = first_nmethod(); var != NULL; var = next_nmethod(var))
bool CodeCache::contains(void *p) {
@@ -687,7 +688,9 @@
void CodeCache::mark_all_nmethods_for_deoptimization() {
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
FOR_ALL_ALIVE_NMETHODS(nm) {
- nm->mark_for_deoptimization();
+ if (!nm->method()->is_method_handle_intrinsic()) {
+ nm->mark_for_deoptimization();
+ }
}
}
@@ -967,6 +970,25 @@
}
}
+void CodeCache::print_codelist(outputStream* st) {
+ assert_locked_or_safepoint(CodeCache_lock);
+
+ FOR_ALL_NMETHODS(p) {
+ ResourceMark rm;
+ char *method_name = p->method()->name_and_sig_as_C_string();
+ st->print_cr("%d %d %s ["INTPTR_FORMAT", "INTPTR_FORMAT" - "INTPTR_FORMAT"]",
+ p->compile_id(), p->comp_level(), method_name, (intptr_t)p->header_begin(),
+ (intptr_t)p->code_begin(), (intptr_t)p->code_end());
+ }
+}
+
+void CodeCache::print_layout(outputStream* st) {
+ assert_locked_or_safepoint(CodeCache_lock);
+ ResourceMark rm;
+
+ print_summary(st, true);
+}
+
void CodeCache::log_state(outputStream* st) {
st->print(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'"
" adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
--- a/hotspot/src/share/vm/code/codeCache.hpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/code/codeCache.hpp Wed Jul 05 20:01:44 2017 +0200
@@ -152,6 +152,10 @@
static void print_summary(outputStream* st, bool detailed = true); // Prints a summary of the code cache usage
static void log_state(outputStream* st);
+ // Dcmd (Diagnostic commands)
+ static void print_codelist(outputStream* st);
+ static void print_layout(outputStream* st);
+
// The full limits of the codeCache
static address low_bound() { return (address) _heap->low_boundary(); }
static address high_bound() { return (address) _heap->high_boundary(); }
--- a/hotspot/src/share/vm/code/compiledIC.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/code/compiledIC.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -595,6 +595,7 @@
} else {
// Callee is interpreted code. In any case entering the interpreter
// puts a converter-frame on the stack to save arguments.
+ assert(!m->is_method_handle_intrinsic(), "Compiled code should never call interpreter MH intrinsics");
info._to_interpreter = true;
info._entry = m()->get_c2i_entry();
}
--- a/hotspot/src/share/vm/code/nmethod.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/code/nmethod.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -2062,7 +2062,7 @@
"metadata must be found in exactly one place");
if (r->metadata_is_immediate() && r->metadata_value() != NULL) {
Metadata* md = r->metadata_value();
- f(md);
+ if (md != _method) f(md);
}
} else if (iter.type() == relocInfo::virtual_call_type) {
// Check compiledIC holders associated with this nmethod
--- a/hotspot/src/share/vm/code/nmethod.hpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/code/nmethod.hpp Wed Jul 05 20:01:44 2017 +0200
@@ -448,7 +448,10 @@
// alive. It is used when an uncommon trap happens. Returns true
// if this thread changed the state of the nmethod or false if
// another thread performed the transition.
- bool make_not_entrant() { return make_not_entrant_or_zombie(not_entrant); }
+ bool make_not_entrant() {
+ assert(!method()->is_method_handle_intrinsic(), "Cannot make MH intrinsic not entrant");
+ return make_not_entrant_or_zombie(not_entrant);
+ }
bool make_zombie() { return make_not_entrant_or_zombie(zombie); }
// used by jvmti to track if the unload event has been reported
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -166,7 +166,7 @@
StringLogMessage lm;
stringStream sstr = lm.stream();
// msg.time_stamp().update_to(tty->time_stamp().ticks());
- task->print_compilation(&sstr, NULL, true);
+ task->print_compilation(&sstr, NULL, true, false);
log(thread, "%s", (const char*)lm);
}
@@ -328,7 +328,6 @@
if (nm == NULL) _code_handle = NULL; // drop the handle also
}
-
void CompileTask::mark_on_stack() {
// Mark these methods as something redefine classes cannot remove.
_method->set_on_stack(true);
@@ -338,18 +337,6 @@
}
// ------------------------------------------------------------------
-// CompileTask::print
-void CompileTask::print() {
- tty->print("<CompileTask compile_id=%d ", _compile_id);
- tty->print("method=");
- _method->print_name(tty);
- tty->print_cr(" osr_bci=%d is_blocking=%s is_complete=%s is_success=%s>",
- _osr_bci, bool_to_str(_is_blocking),
- bool_to_str(_is_complete), bool_to_str(_is_success));
-}
-
-
-// ------------------------------------------------------------------
// CompileTask::print_line_on_error
//
// This function is called by fatal error handler when the thread
@@ -367,19 +354,18 @@
// ------------------------------------------------------------------
// CompileTask::print_line
-void CompileTask::print_line() {
+void CompileTask::print_tty() {
ttyLocker ttyl; // keep the following output all in one block
// print compiler name if requested
if (CIPrintCompilerName) tty->print("%s:", CompileBroker::compiler_name(comp_level()));
- print_compilation();
+ print_compilation(tty);
}
-
// ------------------------------------------------------------------
// CompileTask::print_compilation_impl
void CompileTask::print_compilation_impl(outputStream* st, Method* method, int compile_id, int comp_level,
bool is_osr_method, int osr_bci, bool is_blocking,
- const char* msg, bool short_form) {
+ const char* msg, bool short_form, bool cr) {
if (!short_form) {
st->print("%7d ", (int) st->time_stamp().milliseconds()); // print timestamp
}
@@ -428,7 +414,7 @@
if (msg != NULL) {
st->print(" %s", msg);
}
- if (!short_form) {
+ if (cr) {
st->cr();
}
}
@@ -494,9 +480,9 @@
// ------------------------------------------------------------------
// CompileTask::print_compilation
-void CompileTask::print_compilation(outputStream* st, const char* msg, bool short_form) {
+void CompileTask::print_compilation(outputStream* st, const char* msg, bool short_form, bool cr) {
bool is_osr_method = osr_bci() != InvocationEntryBci;
- print_compilation_impl(st, method(), compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), msg, short_form);
+ print_compilation_impl(st, method(), compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), msg, short_form, cr);
}
// ------------------------------------------------------------------
@@ -621,7 +607,9 @@
// Mark the method as being in the compile queue.
task->method()->set_queued_for_compilation();
- NOT_PRODUCT(print();)
+ if (CIPrintCompileQueue) {
+ print_tty();
+ }
if (LogCompilation && xtty != NULL) {
task->log_task_queued();
@@ -786,24 +774,40 @@
}
}
-#ifndef PRODUCT
-/**
- * Print entire compilation queue.
- */
-void CompileQueue::print() {
- if (CIPrintCompileQueue) {
- ttyLocker ttyl;
- tty->print_cr("Contents of %s", name());
- tty->print_cr("----------------------");
- CompileTask* task = _first;
+
+CompileQueue* CompileBroker::compile_queue(int comp_level) {
+ if (is_c2_compile(comp_level)) return _c2_compile_queue;
+ if (is_c1_compile(comp_level)) return _c1_compile_queue;
+ return NULL;
+}
+
+
+void CompileBroker::print_compile_queues(outputStream* st) {
+ _c1_compile_queue->print(st);
+ _c2_compile_queue->print(st);
+}
+
+
+void CompileQueue::print(outputStream* st) {
+ assert_locked_or_safepoint(lock());
+ st->print_cr("Contents of %s", name());
+ st->print_cr("----------------------------");
+ CompileTask* task = _first;
+ if (task == NULL) {
+ st->print_cr("Empty");;
+ } else {
while (task != NULL) {
- task->print_line();
+ task->print_compilation(st, NULL, true, true);
task = task->next();
}
- tty->print_cr("----------------------");
}
+ st->print_cr("----------------------------");
}
-#endif // PRODUCT
+
+void CompileQueue::print_tty() {
+ ttyLocker ttyl;
+ print(tty);
+}
CompilerCounters::CompilerCounters(const char* thread_name, int instance, TRAPS) {
@@ -1068,11 +1072,11 @@
#endif // !ZERO && !SHARK
// Initialize the compilation queue
if (c2_compiler_count > 0) {
- _c2_compile_queue = new CompileQueue("C2 CompileQueue", MethodCompileQueue_lock);
+ _c2_compile_queue = new CompileQueue("C2 compile queue", MethodCompileQueue_lock);
_compilers[1]->set_num_compiler_threads(c2_compiler_count);
}
if (c1_compiler_count > 0) {
- _c1_compile_queue = new CompileQueue("C1 CompileQueue", MethodCompileQueue_lock);
+ _c1_compile_queue = new CompileQueue("C1 compile queue", MethodCompileQueue_lock);
_compilers[0]->set_num_compiler_threads(c1_compiler_count);
}
@@ -1892,7 +1896,7 @@
void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
if (PrintCompilation) {
ResourceMark rm;
- task->print_line();
+ task->print_tty();
}
elapsedTimer time;
--- a/hotspot/src/share/vm/compiler/compileBroker.hpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/compiler/compileBroker.hpp Wed Jul 05 20:01:44 2017 +0200
@@ -111,14 +111,14 @@
private:
static void print_compilation_impl(outputStream* st, Method* method, int compile_id, int comp_level,
bool is_osr_method = false, int osr_bci = -1, bool is_blocking = false,
- const char* msg = NULL, bool short_form = false);
+ const char* msg = NULL, bool short_form = false, bool cr = true);
public:
- void print_compilation(outputStream* st = tty, const char* msg = NULL, bool short_form = false);
- static void print_compilation(outputStream* st, const nmethod* nm, const char* msg = NULL, bool short_form = false) {
+ void print_compilation(outputStream* st = tty, const char* msg = NULL, bool short_form = false, bool cr = true);
+ static void print_compilation(outputStream* st, const nmethod* nm, const char* msg = NULL, bool short_form = false, bool cr = true) {
print_compilation_impl(st, nm->method(), nm->compile_id(), nm->comp_level(),
nm->is_osr_method(), nm->is_osr_method() ? nm->osr_entry_bci() : -1, /*is_blocking*/ false,
- msg, short_form);
+ msg, short_form, cr);
}
static void print_inlining(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg = NULL);
@@ -131,8 +131,7 @@
static void print_inline_indent(int inline_level, outputStream* st = tty);
- void print();
- void print_line();
+ void print_tty();
void print_line_on_error(outputStream* st, char* buf, int buflen);
void log_task(xmlStream* log);
@@ -234,7 +233,8 @@
// Redefine Classes support
void mark_on_stack();
void free_all();
- NOT_PRODUCT (void print();)
+ void print_tty();
+ void print(outputStream* st = tty);
~CompileQueue() {
assert (is_empty(), " Compile Queue must be empty");
@@ -341,7 +341,7 @@
static void init_compiler_threads(int c1_compiler_count, int c2_compiler_count);
static bool compilation_is_complete (methodHandle method, int osr_bci, int comp_level);
static bool compilation_is_prohibited(methodHandle method, int osr_bci, int comp_level);
- static bool is_compile_blocking ();
+ static bool is_compile_blocking();
static void preload_classes (methodHandle method, TRAPS);
static CompileTask* create_compile_task(CompileQueue* queue,
@@ -369,11 +369,8 @@
int hot_count,
const char* comment,
Thread* thread);
- static CompileQueue* compile_queue(int comp_level) {
- if (is_c2_compile(comp_level)) return _c2_compile_queue;
- if (is_c1_compile(comp_level)) return _c1_compile_queue;
- return NULL;
- }
+
+ static CompileQueue* compile_queue(int comp_level);
static bool init_compiler_runtime();
static void shutdown_compiler_runtime(AbstractCompiler* comp, CompilerThread* thread);
@@ -390,6 +387,7 @@
}
static bool compilation_is_in_queue(methodHandle method);
+ static void print_compile_queues(outputStream* st);
static int queue_size(int comp_level) {
CompileQueue *q = compile_queue(comp_level);
return q != NULL ? q->size() : 0;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -369,33 +369,45 @@
#endif
}
-bool
-G1BlockOffsetArray::verify_for_object(HeapWord* obj_start,
- size_t word_size) const {
- size_t first_card = _array->index_for(obj_start);
- size_t last_card = _array->index_for(obj_start + word_size - 1);
- if (!_array->is_card_boundary(obj_start)) {
- // If the object is not on a card boundary the BOT entry of the
- // first card should point to another object so we should not
- // check that one.
- first_card += 1;
- }
- for (size_t card = first_card; card <= last_card; card += 1) {
- HeapWord* card_addr = _array->address_for_index(card);
- HeapWord* block_start = block_start_const(card_addr);
- if (block_start != obj_start) {
- gclog_or_tty->print_cr("block start: "PTR_FORMAT" is incorrect - "
- "card index: "SIZE_FORMAT" "
- "card addr: "PTR_FORMAT" BOT entry: %u "
- "obj: "PTR_FORMAT" word size: "SIZE_FORMAT" "
- "cards: ["SIZE_FORMAT","SIZE_FORMAT"]",
- p2i(block_start), card, p2i(card_addr),
- _array->offset_array(card),
- p2i(obj_start), word_size, first_card, last_card);
- return false;
+void G1BlockOffsetArray::verify() const {
+ assert(gsp()->bottom() < gsp()->top(), "Only non-empty regions should be verified.");
+ size_t start_card = _array->index_for(gsp()->bottom());
+ size_t end_card = _array->index_for(gsp()->top() - 1);
+
+ for (size_t current_card = start_card; current_card < end_card; current_card++) {
+ u_char entry = _array->offset_array(current_card);
+ if (entry < N_words) {
+ // The entry should point to an object before the current card. Verify that
+ // it is possible to walk from that object in to the current card by just
+ // iterating over the objects following it.
+ HeapWord* card_address = _array->address_for_index(current_card);
+ HeapWord* obj_end = card_address - entry;
+ while (obj_end < card_address) {
+ HeapWord* obj = obj_end;
+ size_t obj_size = block_size(obj);
+ obj_end = obj + obj_size;
+ guarantee(obj_end > obj && obj_end <= gsp()->top(),
+ err_msg("Invalid object end. obj: " PTR_FORMAT " obj_size: " SIZE_FORMAT " obj_end: " PTR_FORMAT " top: " PTR_FORMAT,
+ p2i(obj), obj_size, p2i(obj_end), p2i(gsp()->top())));
+ }
+ } else {
+ // Because we refine the BOT based on which cards are dirty there is not much we can verify here.
+ // We need to make sure that we are going backwards and that we don't pass the start of the
+ // corresponding heap region. But that is about all we can verify.
+ size_t backskip = BlockOffsetArray::entry_to_cards_back(entry);
+ guarantee(backskip >= 1, "Must be going back at least one card.");
+
+ size_t max_backskip = current_card - start_card;
+ guarantee(backskip <= max_backskip,
+ err_msg("Going backwards beyond the start_card. start_card: " SIZE_FORMAT " current_card: " SIZE_FORMAT " backskip: " SIZE_FORMAT,
+ start_card, current_card, backskip));
+
+ HeapWord* backskip_address = _array->address_for_index(current_card - backskip);
+ guarantee(backskip_address >= gsp()->bottom(),
+ err_msg("Going backwards beyond bottom of the region: bottom: " PTR_FORMAT ", backskip_address: " PTR_FORMAT,
+ p2i(gsp()->bottom()), p2i(backskip_address)));
}
}
- return true;
}
#ifndef PRODUCT
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Wed Jul 05 20:01:44 2017 +0200
@@ -304,13 +304,9 @@
virtual HeapWord* block_start_unsafe(const void* addr);
virtual HeapWord* block_start_unsafe_const(const void* addr) const;
- // Used by region verification. Checks that the contents of the
- // BOT reflect that there's a single object that spans the address
- // range [obj_start, obj_start + word_size); returns true if this is
- // the case, returns false if it's not.
- bool verify_for_object(HeapWord* obj_start, size_t word_size) const;
+ void check_all_cards(size_t left_card, size_t right_card) const;
- void check_all_cards(size_t left_card, size_t right_card) const;
+ void verify() const;
virtual void print_on(outputStream* out) PRODUCT_RETURN;
};
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -48,6 +48,7 @@
return hash ^ (hash >> 7); // code heap blocks are 128byte aligned
}
+ void remove_entry(Entry* e, Entry* previous);
Entry* new_entry(nmethod* nm);
public:
@@ -67,7 +68,7 @@
void nmethods_do(CodeBlobClosure* blk);
template<typename CB>
- void remove_if(CB& should_remove);
+ int remove_if(CB& should_remove);
static void purge_list_append(CodeRootSetTable* tbl);
static void purge();
@@ -91,6 +92,18 @@
return entry;
}
+void CodeRootSetTable::remove_entry(Entry* e, Entry* previous) {
+ int index = hash_to_index(e->hash());
+ assert((e == bucket(index)) == (previous == NULL), "if e is the first entry then previous should be null");
+
+ if (previous == NULL) {
+ set_entry(index, e->next());
+ } else {
+ previous->set_next(e->next());
+ }
+ free_entry(e);
+}
+
CodeRootSetTable::~CodeRootSetTable() {
for (int index = 0; index < table_size(); ++index) {
for (Entry* e = bucket(index); e != NULL; ) {
@@ -133,12 +146,7 @@
Entry* previous = NULL;
for (Entry* e = bucket(index); e != NULL; previous = e, e = e->next()) {
if (e->literal() == nm) {
- if (previous != NULL) {
- previous->set_next(e->next());
- } else {
- set_entry(index, e->next());
- }
- free_entry(e);
+ remove_entry(e, previous);
return true;
}
}
@@ -163,25 +171,23 @@
}
template<typename CB>
-void CodeRootSetTable::remove_if(CB& should_remove) {
+int CodeRootSetTable::remove_if(CB& should_remove) {
+ int num_removed = 0;
for (int index = 0; index < table_size(); ++index) {
Entry* previous = NULL;
Entry* e = bucket(index);
while (e != NULL) {
Entry* next = e->next();
if (should_remove(e->literal())) {
- if (previous != NULL) {
- previous->set_next(next);
- } else {
- set_entry(index, next);
- }
- free_entry(e);
+ remove_entry(e, previous);
+ ++num_removed;
} else {
previous = e;
}
e = next;
}
}
+ return num_removed;
}
G1CodeRootSet::~G1CodeRootSet() {
@@ -320,14 +326,19 @@
bool operator() (nmethod* nm) {
_detector._points_into = false;
_blobs.do_code_blob(nm);
- return _detector._points_into;
+ return !_detector._points_into;
}
};
void G1CodeRootSet::clean(HeapRegion* owner) {
CleanCallback should_clean(owner);
if (_table != NULL) {
- _table->remove_if(should_clean);
+ int removed = _table->remove_if(should_clean);
+ assert((size_t)removed <= _length, "impossible");
+ _length -= removed;
+ }
+ if (_length == 0) {
+ clear();
}
}
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -861,7 +861,6 @@
HeapWord* prev_p = NULL;
VerifyLiveClosure vl_cl(g1, vo);
bool is_humongous = isHumongous();
- bool do_bot_verify = !is_young();
size_t object_num = 0;
while (p < top()) {
oop obj = oop(p);
@@ -878,15 +877,6 @@
return;
}
- // If it returns false, verify_for_object() will output the
- // appropriate message.
- if (do_bot_verify &&
- !g1->is_obj_dead(obj, this) &&
- !_offsets.verify_for_object(p, obj_size)) {
- *failures = true;
- return;
- }
-
if (!g1->is_obj_dead_cond(obj, this, vo)) {
if (obj->is_oop()) {
Klass* klass = obj->klass();
@@ -924,6 +914,10 @@
p += obj_size;
}
+ if (!is_young() && !is_empty()) {
+ _offsets.verify();
+ }
+
if (p != top()) {
gclog_or_tty->print_cr("end of last object "PTR_FORMAT" "
"does not match top "PTR_FORMAT, p, top());
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -460,6 +460,8 @@
oop InstanceKlass::init_lock() const {
// return the init lock from the mirror
oop lock = java_lang_Class::init_lock(java_mirror());
+ // Prevent reordering with any access of initialization state
+ OrderAccess::loadload();
assert((oop)lock != NULL || !is_not_initialized(), // initialized or in_error state
"only fully initialized state can have a null lock");
return lock;
@@ -2437,16 +2439,6 @@
assert(breakpoints() == 0x0, "should have cleared breakpoints");
}
- // deallocate information about previous versions
- if (_previous_versions != NULL) {
- for (int i = _previous_versions->length() - 1; i >= 0; i--) {
- PreviousVersionNode * pv_node = _previous_versions->at(i);
- delete pv_node;
- }
- delete _previous_versions;
- _previous_versions = NULL;
- }
-
// deallocate the cached class file
if (_cached_class_file != NULL) {
os::free(_cached_class_file, mtClass);
@@ -3020,16 +3012,17 @@
st->print(BULLET"field type annotations: "); fields_type_annotations()->print_value_on(st); st->cr();
{
bool have_pv = false;
- PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this);
- for (PreviousVersionNode * pv_node = pvw.next_previous_version();
- pv_node != NULL; pv_node = pvw.next_previous_version()) {
+ // previous versions are linked together through the InstanceKlass
+ for (InstanceKlass* pv_node = _previous_versions;
+ pv_node != NULL;
+ pv_node = pv_node->previous_versions()) {
if (!have_pv)
st->print(BULLET"previous version: ");
have_pv = true;
- pv_node->prev_constant_pool()->print_value_on(st);
+ pv_node->constants()->print_value_on(st);
}
if (have_pv) st->cr();
- } // pvw is cleaned up
+ }
if (generic_signature() != NULL) {
st->print(BULLET"generic signature: ");
@@ -3443,92 +3436,92 @@
// RedefineClasses() support for previous versions:
// Purge previous versions
-static void purge_previous_versions_internal(InstanceKlass* ik, int emcp_method_count) {
+void InstanceKlass::purge_previous_versions(InstanceKlass* ik) {
if (ik->previous_versions() != NULL) {
// This klass has previous versions so see what we can cleanup
// while it is safe to do so.
int deleted_count = 0; // leave debugging breadcrumbs
int live_count = 0;
- ClassLoaderData* loader_data = ik->class_loader_data() == NULL ?
- ClassLoaderData::the_null_class_loader_data() :
- ik->class_loader_data();
+ ClassLoaderData* loader_data = ik->class_loader_data();
+ assert(loader_data != NULL, "should never be null");
// RC_TRACE macro has an embedded ResourceMark
- RC_TRACE(0x00000200, ("purge: %s: previous version length=%d",
- ik->external_name(), ik->previous_versions()->length()));
-
- for (int i = ik->previous_versions()->length() - 1; i >= 0; i--) {
- // check the previous versions array
- PreviousVersionNode * pv_node = ik->previous_versions()->at(i);
- ConstantPool* cp_ref = pv_node->prev_constant_pool();
- assert(cp_ref != NULL, "cp ref was unexpectedly cleared");
-
- ConstantPool* pvcp = cp_ref;
+ RC_TRACE(0x00000200, ("purge: %s: previous versions", ik->external_name()));
+
+ // previous versions are linked together through the InstanceKlass
+ InstanceKlass* pv_node = ik->previous_versions();
+ InstanceKlass* last = ik;
+ int version = 0;
+
+ // check the previous versions list
+ for (; pv_node != NULL; ) {
+
+ ConstantPool* pvcp = pv_node->constants();
+ assert(pvcp != NULL, "cp ref was unexpectedly cleared");
+
if (!pvcp->on_stack()) {
// If the constant pool isn't on stack, none of the methods
- // are executing. Delete all the methods, the constant pool and
- // and this previous version node.
- GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods();
- if (method_refs != NULL) {
- for (int j = method_refs->length() - 1; j >= 0; j--) {
- Method* method = method_refs->at(j);
- assert(method != NULL, "method ref was unexpectedly cleared");
- method_refs->remove_at(j);
- // method will be freed with associated class.
- }
- }
- // Remove the constant pool
- delete pv_node;
- // Since we are traversing the array backwards, we don't have to
- // do anything special with the index.
- ik->previous_versions()->remove_at(i);
+ // are executing. Unlink this previous_version.
+ // The previous version InstanceKlass is on the ClassLoaderData deallocate list
+ // so will be deallocated during the next phase of class unloading.
+ pv_node = pv_node->previous_versions();
+ last->link_previous_versions(pv_node);
deleted_count++;
+ version++;
continue;
} else {
- RC_TRACE(0x00000200, ("purge: previous version @%d is alive", i));
+ RC_TRACE(0x00000200, ("purge: previous version " INTPTR_FORMAT " is alive",
+ pv_node));
assert(pvcp->pool_holder() != NULL, "Constant pool with no holder");
guarantee (!loader_data->is_unloading(), "unloaded classes can't be on the stack");
live_count++;
}
- // At least one method is live in this previous version, clean out
- // the others or mark them as obsolete.
- GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods();
+ // At least one method is live in this previous version so clean its MethodData.
+ // Reset dead EMCP methods not to get breakpoints.
+ // All methods are deallocated when all of the methods for this class are no
+ // longer running.
+ Array<Method*>* method_refs = pv_node->methods();
if (method_refs != NULL) {
RC_TRACE(0x00000200, ("purge: previous methods length=%d",
method_refs->length()));
- for (int j = method_refs->length() - 1; j >= 0; j--) {
+ for (int j = 0; j < method_refs->length(); j++) {
Method* method = method_refs->at(j);
- assert(method != NULL, "method ref was unexpectedly cleared");
-
- // Remove the emcp method if it's not executing
- // If it's been made obsolete by a redefinition of a non-emcp
- // method, mark it as obsolete but leave it to clean up later.
+
if (!method->on_stack()) {
- method_refs->remove_at(j);
- } else if (emcp_method_count == 0) {
- method->set_is_obsolete();
+ // no breakpoints for non-running methods
+ if (method->is_running_emcp()) {
+ method->set_running_emcp(false);
+ }
} else {
+ assert (method->is_obsolete() || method->is_running_emcp(),
+ "emcp method cannot run after emcp bit is cleared");
// RC_TRACE macro has an embedded ResourceMark
RC_TRACE(0x00000200,
("purge: %s(%s): prev method @%d in version @%d is alive",
method->name()->as_C_string(),
- method->signature()->as_C_string(), j, i));
+ method->signature()->as_C_string(), j, version));
if (method->method_data() != NULL) {
- // Clean out any weak method links
+ // Clean out any weak method links for running methods
+ // (also should include not EMCP methods)
method->method_data()->clean_weak_method_links();
}
}
}
}
+ // next previous version
+ last = pv_node;
+ pv_node = pv_node->previous_versions();
+ version++;
}
- assert(ik->previous_versions()->length() == live_count, "sanity check");
RC_TRACE(0x00000200,
("purge: previous version stats: live=%d, deleted=%d", live_count,
deleted_count));
}
+ // Clean MethodData of this class's methods so they don't refer to
+ // old methods that are no longer running.
Array<Method*>* methods = ik->methods();
int num_methods = methods->length();
for (int index2 = 0; index2 < num_methods; ++index2) {
@@ -3538,122 +3531,30 @@
}
}
-// External interface for use during class unloading.
-void InstanceKlass::purge_previous_versions(InstanceKlass* ik) {
- // Call with >0 emcp methods since they are not currently being redefined.
- purge_previous_versions_internal(ik, 1);
-}
-
-
-// Potentially add an information node that contains pointers to the
-// interesting parts of the previous version of the_class.
-// This is also where we clean out any unused references.
-// Note that while we delete nodes from the _previous_versions
-// array, we never delete the array itself until the klass is
-// unloaded. The has_been_redefined() query depends on that fact.
-//
-void InstanceKlass::add_previous_version(instanceKlassHandle ikh,
- BitMap* emcp_methods, int emcp_method_count) {
- assert(Thread::current()->is_VM_thread(),
- "only VMThread can add previous versions");
-
- if (_previous_versions == NULL) {
- // This is the first previous version so make some space.
- // Start with 2 elements under the assumption that the class
- // won't be redefined much.
- _previous_versions = new (ResourceObj::C_HEAP, mtClass)
- GrowableArray<PreviousVersionNode *>(2, true);
- }
-
- ConstantPool* cp_ref = ikh->constants();
-
- // RC_TRACE macro has an embedded ResourceMark
- RC_TRACE(0x00000400, ("adding previous version ref for %s @%d, EMCP_cnt=%d "
- "on_stack=%d",
- ikh->external_name(), _previous_versions->length(), emcp_method_count,
- cp_ref->on_stack()));
-
- // If the constant pool for this previous version of the class
- // is not marked as being on the stack, then none of the methods
- // in this previous version of the class are on the stack so
- // we don't need to create a new PreviousVersionNode. However,
- // we still need to examine older previous versions below.
- Array<Method*>* old_methods = ikh->methods();
-
- if (cp_ref->on_stack()) {
- PreviousVersionNode * pv_node = NULL;
- if (emcp_method_count == 0) {
- // non-shared ConstantPool gets a reference
- pv_node = new PreviousVersionNode(cp_ref, NULL);
- RC_TRACE(0x00000400,
- ("add: all methods are obsolete; flushing any EMCP refs"));
- } else {
- int local_count = 0;
- GrowableArray<Method*>* method_refs = new (ResourceObj::C_HEAP, mtClass)
- GrowableArray<Method*>(emcp_method_count, true);
- for (int i = 0; i < old_methods->length(); i++) {
- if (emcp_methods->at(i)) {
- // this old method is EMCP. Save it only if it's on the stack
- Method* old_method = old_methods->at(i);
- if (old_method->on_stack()) {
- method_refs->append(old_method);
- }
- if (++local_count >= emcp_method_count) {
- // no more EMCP methods so bail out now
- break;
- }
- }
- }
- // non-shared ConstantPool gets a reference
- pv_node = new PreviousVersionNode(cp_ref, method_refs);
- }
- // append new previous version.
- _previous_versions->append(pv_node);
- }
-
- // Since the caller is the VMThread and we are at a safepoint, this
- // is a good time to clear out unused references.
-
- RC_TRACE(0x00000400, ("add: previous version length=%d",
- _previous_versions->length()));
-
- // Purge previous versions not executing on the stack
- purge_previous_versions_internal(this, emcp_method_count);
-
+void InstanceKlass::mark_newly_obsolete_methods(Array<Method*>* old_methods,
+ int emcp_method_count) {
int obsolete_method_count = old_methods->length() - emcp_method_count;
if (emcp_method_count != 0 && obsolete_method_count != 0 &&
- _previous_versions->length() > 0) {
+ _previous_versions != NULL) {
// We have a mix of obsolete and EMCP methods so we have to
// clear out any matching EMCP method entries the hard way.
int local_count = 0;
for (int i = 0; i < old_methods->length(); i++) {
- if (!emcp_methods->at(i)) {
+ Method* old_method = old_methods->at(i);
+ if (old_method->is_obsolete()) {
// only obsolete methods are interesting
- Method* old_method = old_methods->at(i);
Symbol* m_name = old_method->name();
Symbol* m_signature = old_method->signature();
- // we might not have added the last entry
- for (int j = _previous_versions->length() - 1; j >= 0; j--) {
- // check the previous versions array for non executing obsolete methods
- PreviousVersionNode * pv_node = _previous_versions->at(j);
-
- GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods();
- if (method_refs == NULL) {
- // We have run into a PreviousVersion generation where
- // all methods were made obsolete during that generation's
- // RedefineClasses() operation. At the time of that
- // operation, all EMCP methods were flushed so we don't
- // have to go back any further.
- //
- // A NULL method_refs is different than an empty method_refs.
- // We cannot infer any optimizations about older generations
- // from an empty method_refs for the current generation.
- break;
- }
-
- for (int k = method_refs->length() - 1; k >= 0; k--) {
+ // previous versions are linked together through the InstanceKlass
+ int j = 0;
+ for (InstanceKlass* prev_version = _previous_versions;
+ prev_version != NULL;
+ prev_version = prev_version->previous_versions(), j++) {
+
+ Array<Method*>* method_refs = prev_version->methods();
+ for (int k = 0; k < method_refs->length(); k++) {
Method* method = method_refs->at(k);
if (!method->is_obsolete() &&
@@ -3661,14 +3562,11 @@
method->signature() == m_signature) {
// The current RedefineClasses() call has made all EMCP
// versions of this method obsolete so mark it as obsolete
- // and remove the reference.
RC_TRACE(0x00000400,
("add: %s(%s): flush obsolete method @%d in version @%d",
m_name->as_C_string(), m_signature->as_C_string(), k, j));
method->set_is_obsolete();
- // Leave obsolete methods on the previous version list to
- // clean up later.
break;
}
}
@@ -3676,9 +3574,9 @@
// The previous loop may not find a matching EMCP method, but
// that doesn't mean that we can optimize and not go any
// further back in the PreviousVersion generations. The EMCP
- // method for this generation could have already been deleted,
+ // method for this generation could have already been made obsolete,
// but there still may be an older EMCP method that has not
- // been deleted.
+ // been made obsolete.
}
if (++local_count >= obsolete_method_count) {
@@ -3688,15 +3586,69 @@
}
}
}
+}
+
+// Save the scratch_class as the previous version if any of the methods are running.
+// The previous_versions are used to set breakpoints in EMCP methods and they are
+// also used to clean MethodData links to redefined methods that are no longer running.
+void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class,
+ int emcp_method_count) {
+ assert(Thread::current()->is_VM_thread(),
+ "only VMThread can add previous versions");
+
+ // RC_TRACE macro has an embedded ResourceMark
+ RC_TRACE(0x00000400, ("adding previous version ref for %s, EMCP_cnt=%d",
+ scratch_class->external_name(), emcp_method_count));
+
+ // Clean out old previous versions
+ purge_previous_versions(this);
+
+ // Mark newly obsolete methods in remaining previous versions. An EMCP method from
+ // a previous redefinition may be made obsolete by this redefinition.
+ Array<Method*>* old_methods = scratch_class->methods();
+ mark_newly_obsolete_methods(old_methods, emcp_method_count);
+
+ // If the constant pool for this previous version of the class
+ // is not marked as being on the stack, then none of the methods
+ // in this previous version of the class are on the stack so
+ // we don't need to add this as a previous version.
+ ConstantPool* cp_ref = scratch_class->constants();
+ if (!cp_ref->on_stack()) {
+ RC_TRACE(0x00000400, ("add: scratch class not added; no methods are running"));
+ return;
+ }
+
+ if (emcp_method_count != 0) {
+ // At least one method is still running, check for EMCP methods
+ for (int i = 0; i < old_methods->length(); i++) {
+ Method* old_method = old_methods->at(i);
+ if (!old_method->is_obsolete() && old_method->on_stack()) {
+ // if EMCP method (not obsolete) is on the stack, mark as EMCP so that
+ // we can add breakpoints for it.
+
+ // We set the method->on_stack bit during safepoints for class redefinition and
+ // class unloading and use this bit to set the is_running_emcp bit.
+ // After the safepoint, the on_stack bit is cleared and the running emcp
+ // method may exit. If so, we would set a breakpoint in a method that
+ // is never reached, but this won't be noticeable to the programmer.
+ old_method->set_running_emcp(true);
+ RC_TRACE(0x00000400, ("add: EMCP method %s is on_stack " INTPTR_FORMAT,
+ old_method->name_and_sig_as_C_string(), old_method));
+ } else if (!old_method->is_obsolete()) {
+ RC_TRACE(0x00000400, ("add: EMCP method %s is NOT on_stack " INTPTR_FORMAT,
+ old_method->name_and_sig_as_C_string(), old_method));
+ }
+ }
+ }
+
+ // Add previous version if any methods are still running.
+ RC_TRACE(0x00000400, ("add: scratch class added; one of its methods is on_stack"));
+ assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version");
+ scratch_class->link_previous_versions(previous_versions());
+ link_previous_versions(scratch_class());
} // end add_previous_version()
-// Determine if InstanceKlass has a previous version.
-bool InstanceKlass::has_previous_version() const {
- return (_previous_versions != NULL && _previous_versions->length() > 0);
-} // end has_previous_version()
-
-
Method* InstanceKlass::method_with_idnum(int idnum) {
Method* m = NULL;
if (idnum < methods()->length()) {
@@ -3722,61 +3674,3 @@
unsigned char * InstanceKlass::get_cached_class_file_bytes() {
return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file);
}
-
-
-// Construct a PreviousVersionNode entry for the array hung off
-// the InstanceKlass.
-PreviousVersionNode::PreviousVersionNode(ConstantPool* prev_constant_pool,
- GrowableArray<Method*>* prev_EMCP_methods) {
-
- _prev_constant_pool = prev_constant_pool;
- _prev_EMCP_methods = prev_EMCP_methods;
-}
-
-
-// Destroy a PreviousVersionNode
-PreviousVersionNode::~PreviousVersionNode() {
- if (_prev_constant_pool != NULL) {
- _prev_constant_pool = NULL;
- }
-
- if (_prev_EMCP_methods != NULL) {
- delete _prev_EMCP_methods;
- }
-}
-
-// Construct a helper for walking the previous versions array
-PreviousVersionWalker::PreviousVersionWalker(Thread* thread, InstanceKlass *ik) {
- _thread = thread;
- _previous_versions = ik->previous_versions();
- _current_index = 0;
- _current_p = NULL;
- _current_constant_pool_handle = constantPoolHandle(thread, ik->constants());
-}
-
-
-// Return the interesting information for the next previous version
-// of the klass. Returns NULL if there are no more previous versions.
-PreviousVersionNode* PreviousVersionWalker::next_previous_version() {
- if (_previous_versions == NULL) {
- // no previous versions so nothing to return
- return NULL;
- }
-
- _current_p = NULL; // reset to NULL
- _current_constant_pool_handle = NULL;
-
- int length = _previous_versions->length();
-
- while (_current_index < length) {
- PreviousVersionNode * pv_node = _previous_versions->at(_current_index++);
-
- // Save a handle to the constant pool for this previous version,
- // which keeps all the methods from being deallocated.
- _current_constant_pool_handle = constantPoolHandle(_thread, pv_node->prev_constant_pool());
- _current_p = pv_node;
- return pv_node;
- }
-
- return NULL;
-} // end next_previous_version()
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Jul 05 20:01:44 2017 +0200
@@ -59,7 +59,6 @@
class fieldDescriptor;
class DepChange;
class nmethodBucket;
-class PreviousVersionNode;
class JvmtiCachedClassFieldMap;
class MemberNameTable;
@@ -205,7 +204,8 @@
_misc_should_verify_class = 1 << 2, // allow caching of preverification
_misc_is_anonymous = 1 << 3, // has embedded _host_klass field
_misc_is_contended = 1 << 4, // marked with contended annotation
- _misc_has_default_methods = 1 << 5 // class/superclass/implemented interfaces has default methods
+ _misc_has_default_methods = 1 << 5, // class/superclass/implemented interfaces has default methods
+ _misc_has_been_redefined = 1 << 6 // class has been redefined
};
u2 _misc_flags;
u2 _minor_version; // minor version number of class file
@@ -220,9 +220,8 @@
nmethodBucket* _dependencies; // list of dependent nmethods
nmethod* _osr_nmethods_head; // Head of list of on-stack replacement nmethods for this class
BreakpointInfo* _breakpoints; // bpt lists, managed by Method*
- // Array of interesting part(s) of the previous version(s) of this
- // InstanceKlass. See PreviousVersionWalker below.
- GrowableArray<PreviousVersionNode *>* _previous_versions;
+ // Linked instanceKlasses of previous versions
+ InstanceKlass* _previous_versions;
// JVMTI fields can be moved to their own structure - see 6315920
// JVMTI: cached class file, before retransformable agent modified it in CFLH
JvmtiCachedClassFileData* _cached_class_file;
@@ -608,19 +607,20 @@
}
// RedefineClasses() support for previous versions:
- void add_previous_version(instanceKlassHandle ikh, BitMap *emcp_methods,
- int emcp_method_count);
- // If the _previous_versions array is non-NULL, then this klass
- // has been redefined at least once even if we aren't currently
- // tracking a previous version.
- bool has_been_redefined() const { return _previous_versions != NULL; }
- bool has_previous_version() const;
+ void add_previous_version(instanceKlassHandle ikh, int emcp_method_count);
+
+ InstanceKlass* previous_versions() const { return _previous_versions; }
+
+ bool has_been_redefined() const {
+ return (_misc_flags & _misc_has_been_redefined) != 0;
+ }
+ void set_has_been_redefined() {
+ _misc_flags |= _misc_has_been_redefined;
+ }
+
void init_previous_versions() {
_previous_versions = NULL;
}
- GrowableArray<PreviousVersionNode *>* previous_versions() const {
- return _previous_versions;
- }
static void purge_previous_versions(InstanceKlass* ik);
@@ -1042,6 +1042,10 @@
// Free CHeap allocated fields.
void release_C_heap_structures();
+
+ // RedefineClasses support
+ void link_previous_versions(InstanceKlass* pv) { _previous_versions = pv; }
+ void mark_newly_obsolete_methods(Array<Method*>* old_methods, int emcp_method_count);
public:
// CDS support - remove and restore oops from metadata. Oops are not shared.
virtual void remove_unshareable_info();
@@ -1141,62 +1145,6 @@
};
-// If breakpoints are more numerous than just JVMTI breakpoints,
-// consider compressing this data structure.
-// It is currently a simple linked list defined in method.hpp.
-
-class BreakpointInfo;
-
-
-// A collection point for interesting information about the previous
-// version(s) of an InstanceKlass. A GrowableArray of PreviousVersionNodes
-// is attached to the InstanceKlass as needed. See PreviousVersionWalker below.
-class PreviousVersionNode : public CHeapObj<mtClass> {
- private:
- ConstantPool* _prev_constant_pool;
-
- // If the previous version of the InstanceKlass doesn't have any
- // EMCP methods, then _prev_EMCP_methods will be NULL. If all the
- // EMCP methods have been collected, then _prev_EMCP_methods can
- // have a length of zero.
- GrowableArray<Method*>* _prev_EMCP_methods;
-
-public:
- PreviousVersionNode(ConstantPool* prev_constant_pool,
- GrowableArray<Method*>* prev_EMCP_methods);
- ~PreviousVersionNode();
- ConstantPool* prev_constant_pool() const {
- return _prev_constant_pool;
- }
- GrowableArray<Method*>* prev_EMCP_methods() const {
- return _prev_EMCP_methods;
- }
-};
-
-
-// Helper object for walking previous versions.
-class PreviousVersionWalker : public StackObj {
- private:
- Thread* _thread;
- GrowableArray<PreviousVersionNode *>* _previous_versions;
- int _current_index;
-
- // A pointer to the current node object so we can handle the deletes.
- PreviousVersionNode* _current_p;
-
- // The constant pool handle keeps all the methods in this class from being
- // deallocated from the metaspace during class unloading.
- constantPoolHandle _current_constant_pool_handle;
-
- public:
- PreviousVersionWalker(Thread* thread, InstanceKlass *ik);
-
- // Return the interesting information for the next previous version
- // of the klass. Returns NULL if there are no more previous versions.
- PreviousVersionNode* next_previous_version();
-};
-
-
//
// nmethodBucket is used to record dependent nmethods for
// deoptimization. nmethod dependencies are actually <klass, method>
--- a/hotspot/src/share/vm/oops/method.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/oops/method.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -1635,34 +1635,34 @@
}
int Method::highest_comp_level() const {
- const MethodData* mdo = method_data();
- if (mdo != NULL) {
- return mdo->highest_comp_level();
+ const MethodCounters* mcs = method_counters();
+ if (mcs != NULL) {
+ return mcs->highest_comp_level();
} else {
return CompLevel_none;
}
}
int Method::highest_osr_comp_level() const {
- const MethodData* mdo = method_data();
- if (mdo != NULL) {
- return mdo->highest_osr_comp_level();
+ const MethodCounters* mcs = method_counters();
+ if (mcs != NULL) {
+ return mcs->highest_osr_comp_level();
} else {
return CompLevel_none;
}
}
void Method::set_highest_comp_level(int level) {
- MethodData* mdo = method_data();
- if (mdo != NULL) {
- mdo->set_highest_comp_level(level);
+ MethodCounters* mcs = method_counters();
+ if (mcs != NULL) {
+ mcs->set_highest_comp_level(level);
}
}
void Method::set_highest_osr_comp_level(int level) {
- MethodData* mdo = method_data();
- if (mdo != NULL) {
- mdo->set_highest_osr_comp_level(level);
+ MethodCounters* mcs = method_counters();
+ if (mcs != NULL) {
+ mcs->set_highest_osr_comp_level(level);
}
}
--- a/hotspot/src/share/vm/oops/method.hpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/oops/method.hpp Wed Jul 05 20:01:44 2017 +0200
@@ -80,7 +80,8 @@
_caller_sensitive = 1 << 1,
_force_inline = 1 << 2,
_dont_inline = 1 << 3,
- _hidden = 1 << 4
+ _hidden = 1 << 4,
+ _running_emcp = 1 << 5
};
u1 _flags;
@@ -688,6 +689,21 @@
void set_is_obsolete() { _access_flags.set_is_obsolete(); }
bool is_deleted() const { return access_flags().is_deleted(); }
void set_is_deleted() { _access_flags.set_is_deleted(); }
+
+ bool is_running_emcp() const {
+ // EMCP methods are old but not obsolete or deleted. Equivalent
+ // Modulo Constant Pool means the method is equivalent except
+ // the constant pool and instructions that access the constant
+ // pool might be different.
+ // If a breakpoint is set in a redefined method, its EMCP methods that are
+ // still running must have a breakpoint also.
+ return (_flags & _running_emcp) != 0;
+ }
+
+ void set_running_emcp(bool x) {
+ _flags = x ? (_flags | _running_emcp) : (_flags & ~_running_emcp);
+ }
+
bool on_stack() const { return access_flags().on_stack(); }
void set_on_stack(const bool value);
--- a/hotspot/src/share/vm/oops/methodCounters.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/oops/methodCounters.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -35,4 +35,40 @@
set_interpreter_throwout_count(0);
set_interpreter_invocation_count(0);
set_nmethod_age(INT_MAX);
+#ifdef TIERED
+ set_prev_time(0);
+ set_rate(0);
+ set_highest_comp_level(0);
+ set_highest_osr_comp_level(0);
+#endif
}
+
+
+int MethodCounters::highest_comp_level() const {
+#ifdef TIERED
+ return _highest_comp_level;
+#else
+ return CompLevel_none;
+#endif
+}
+
+void MethodCounters::set_highest_comp_level(int level) {
+#ifdef TIERED
+ _highest_comp_level = level;
+#endif
+}
+
+int MethodCounters::highest_osr_comp_level() const {
+#ifdef TIERED
+ return _highest_osr_comp_level;
+#else
+ return CompLevel_none;
+#endif
+}
+
+void MethodCounters::set_highest_osr_comp_level(int level) {
+#ifdef TIERED
+ _highest_osr_comp_level = level;
+#endif
+}
+
--- a/hotspot/src/share/vm/oops/methodCounters.hpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/oops/methodCounters.hpp Wed Jul 05 20:01:44 2017 +0200
@@ -49,6 +49,8 @@
#ifdef TIERED
float _rate; // Events (invocation and backedge counter increments) per millisecond
jlong _prev_time; // Previous time the rate was acquired
+ u1 _highest_comp_level; // Highest compile level this method has ever seen.
+ u1 _highest_osr_comp_level; // Same for OSR level
#endif
MethodCounters() : _interpreter_invocation_count(0),
@@ -57,7 +59,9 @@
_nmethod_age(INT_MAX)
#ifdef TIERED
, _rate(0),
- _prev_time(0)
+ _prev_time(0),
+ _highest_comp_level(0),
+ _highest_osr_comp_level(0)
#endif
{
invocation_counter()->init();
@@ -114,6 +118,11 @@
void set_rate(float rate) { _rate = rate; }
#endif
+ int highest_comp_level() const;
+ void set_highest_comp_level(int level);
+ int highest_osr_comp_level() const;
+ void set_highest_osr_comp_level(int level);
+
// invocation counter
InvocationCounter* invocation_counter() { return &_invocation_counter; }
InvocationCounter* backedge_counter() { return &_backedge_counter; }
--- a/hotspot/src/share/vm/oops/methodData.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/oops/methodData.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -1134,8 +1134,6 @@
_tenure_traps = 0;
_num_loops = 0;
_num_blocks = 0;
- _highest_comp_level = 0;
- _highest_osr_comp_level = 0;
_would_profile = true;
#if INCLUDE_RTM_OPT
--- a/hotspot/src/share/vm/oops/methodData.hpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/oops/methodData.hpp Wed Jul 05 20:01:44 2017 +0200
@@ -2095,10 +2095,6 @@
// time with C1. It is used to determine if method is trivial.
short _num_loops;
short _num_blocks;
- // Highest compile level this method has ever seen.
- u1 _highest_comp_level;
- // Same for OSR level
- u1 _highest_osr_comp_level;
// Does this method contain anything worth profiling?
bool _would_profile;
@@ -2277,11 +2273,6 @@
void set_would_profile(bool p) { _would_profile = p; }
bool would_profile() const { return _would_profile; }
- int highest_comp_level() const { return _highest_comp_level; }
- void set_highest_comp_level(int level) { _highest_comp_level = level; }
- int highest_osr_comp_level() const { return _highest_osr_comp_level; }
- void set_highest_osr_comp_level(int level) { _highest_osr_comp_level = level; }
-
int num_loops() const { return _num_loops; }
void set_num_loops(int n) { _num_loops = n; }
int num_blocks() const { return _num_blocks; }
--- a/hotspot/src/share/vm/opto/compile.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/opto/compile.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -430,7 +430,7 @@
// removes the need to bang the stack in the deoptimization blob which
// in turn simplifies stack overflow handling.
int Compile::bang_size_in_bytes() const {
- return MAX2(_interpreter_frame_size, frame_size_in_bytes());
+ return MAX2(frame_size_in_bytes() + os::extra_bang_size_in_bytes(), _interpreter_frame_size);
}
// ============================================================================
--- a/hotspot/src/share/vm/opto/library_call.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -4968,7 +4968,8 @@
// Allocate the result array
Node* zlen = _gvn.transform(new AddINode(xlen, ylen));
- Node* klass_node = makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_INT)));
+ ciKlass* klass = ciTypeArrayKlass::make(T_INT);
+ Node* klass_node = makecon(TypeKlassPtr::make(klass));
IdealKit ideal(this);
@@ -5002,7 +5003,8 @@
sync_kit(ideal);
z = __ value(z_alloc);
- _gvn.set_type(z, TypeAryPtr::INTS);
+ // Can't use TypeAryPtr::INTS which uses Bottom offset.
+ _gvn.set_type(z, TypeOopPtr::make_from_klass(klass));
// Final sync IdealKit and GraphKit.
final_sync(ideal);
#undef __
--- a/hotspot/src/share/vm/prims/jvmtiImpl.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiImpl.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -282,39 +282,22 @@
void JvmtiBreakpoint::each_method_version_do(method_action meth_act) {
((Method*)_method->*meth_act)(_bci);
- // add/remove breakpoint to/from versions of the method that
- // are EMCP. Directly or transitively obsolete methods are
- // not saved in the PreviousVersionNodes.
+ // add/remove breakpoint to/from versions of the method that are EMCP.
Thread *thread = Thread::current();
instanceKlassHandle ikh = instanceKlassHandle(thread, _method->method_holder());
Symbol* m_name = _method->name();
Symbol* m_signature = _method->signature();
// search previous versions if they exist
- PreviousVersionWalker pvw(thread, (InstanceKlass *)ikh());
- for (PreviousVersionNode * pv_node = pvw.next_previous_version();
- pv_node != NULL; pv_node = pvw.next_previous_version()) {
- GrowableArray<Method*>* methods = pv_node->prev_EMCP_methods();
-
- if (methods == NULL) {
- // We have run into a PreviousVersion generation where
- // all methods were made obsolete during that generation's
- // RedefineClasses() operation. At the time of that
- // operation, all EMCP methods were flushed so we don't
- // have to go back any further.
- //
- // A NULL methods array is different than an empty methods
- // array. We cannot infer any optimizations about older
- // generations from an empty methods array for the current
- // generation.
- break;
- }
+ for (InstanceKlass* pv_node = ikh->previous_versions();
+ pv_node != NULL;
+ pv_node = pv_node->previous_versions()) {
+ Array<Method*>* methods = pv_node->methods();
for (int i = methods->length() - 1; i >= 0; i--) {
Method* method = methods->at(i);
- // obsolete methods that are running are not deleted from
- // previous version array, but they are skipped here.
- if (!method->is_obsolete() &&
+ // Only set breakpoints in running EMCP methods.
+ if (method->is_running_emcp() &&
method->name() == m_name &&
method->signature() == m_signature) {
RC_TRACE(0x00000800, ("%sing breakpoint in %s(%s)",
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -135,7 +135,7 @@
// Mark methods seen on stack and everywhere else so old methods are not
// cleaned up if they're on the stack.
- MetadataOnStackMark md_on_stack;
+ MetadataOnStackMark md_on_stack(true);
HandleMark hm(thread); // make sure any handles created are deleted
// before the stack walk again.
@@ -2826,11 +2826,10 @@
}
// the previous versions' constant pool caches may need adjustment
- PreviousVersionWalker pvw(_thread, ik);
- for (PreviousVersionNode * pv_node = pvw.next_previous_version();
- pv_node != NULL; pv_node = pvw.next_previous_version()) {
- other_cp = pv_node->prev_constant_pool();
- cp_cache = other_cp->cache();
+ for (InstanceKlass* pv_node = ik->previous_versions();
+ pv_node != NULL;
+ pv_node = pv_node->previous_versions()) {
+ cp_cache = pv_node->constants()->cache();
if (cp_cache != NULL) {
cp_cache->adjust_method_entries(_matching_old_methods,
_matching_new_methods,
@@ -2855,9 +2854,8 @@
}
}
-void VM_RedefineClasses::check_methods_and_mark_as_obsolete(
- BitMap *emcp_methods, int * emcp_method_count_p) {
- *emcp_method_count_p = 0;
+int VM_RedefineClasses::check_methods_and_mark_as_obsolete() {
+ int emcp_method_count = 0;
int obsolete_count = 0;
int old_index = 0;
for (int j = 0; j < _matching_methods_length; ++j, ++old_index) {
@@ -2931,9 +2929,9 @@
// that we get from effectively overwriting the old methods
// when the new methods are attached to the_class.
- // track which methods are EMCP for add_previous_version() call
- emcp_methods->set_bit(old_index);
- (*emcp_method_count_p)++;
+ // Count number of methods that are EMCP. The method will be marked
+ // old but not obsolete if it is EMCP.
+ emcp_method_count++;
// An EMCP method is _not_ obsolete. An obsolete method has a
// different jmethodID than the current method. An EMCP method
@@ -2982,10 +2980,11 @@
old_method->name()->as_C_string(),
old_method->signature()->as_C_string()));
}
- assert((*emcp_method_count_p + obsolete_count) == _old_methods->length(),
+ assert((emcp_method_count + obsolete_count) == _old_methods->length(),
"sanity check");
- RC_TRACE(0x00000100, ("EMCP_cnt=%d, obsolete_cnt=%d", *emcp_method_count_p,
+ RC_TRACE(0x00000100, ("EMCP_cnt=%d, obsolete_cnt=%d", emcp_method_count,
obsolete_count));
+ return emcp_method_count;
}
// This internal class transfers the native function registration from old methods
@@ -3379,11 +3378,8 @@
old_constants->set_pool_holder(scratch_class());
#endif
- // track which methods are EMCP for add_previous_version() call below
- BitMap emcp_methods(_old_methods->length());
- int emcp_method_count = 0;
- emcp_methods.clear(); // clears 0..(length() - 1)
- check_methods_and_mark_as_obsolete(&emcp_methods, &emcp_method_count);
+ // track number of methods that are EMCP for add_previous_version() call below
+ int emcp_method_count = check_methods_and_mark_as_obsolete();
transfer_old_native_function_registrations(the_class);
// The class file bytes from before any retransformable agents mucked
@@ -3471,9 +3467,10 @@
scratch_class->enclosing_method_method_index());
scratch_class->set_enclosing_method_indices(old_class_idx, old_method_idx);
+ the_class->set_has_been_redefined();
+
// keep track of previous versions of this class
- the_class->add_previous_version(scratch_class, &emcp_methods,
- emcp_method_count);
+ the_class->add_previous_version(scratch_class, emcp_method_count);
RC_TIMER_STOP(_timer_rsc_phase1);
RC_TIMER_START(_timer_rsc_phase2);
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp Wed Jul 05 20:01:44 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, 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
@@ -403,14 +403,9 @@
// Change jmethodIDs to point to the new methods
void update_jmethod_ids();
- // In addition to marking methods as obsolete, this routine
- // records which methods are EMCP (Equivalent Module Constant
- // Pool) in the emcp_methods BitMap and returns the number of
- // EMCP methods via emcp_method_count_p. This information is
- // used when information about the previous version of the_class
- // is squirreled away.
- void check_methods_and_mark_as_obsolete(BitMap *emcp_methods,
- int * emcp_method_count_p);
+ // In addition to marking methods as old and/or obsolete, this routine
+ // counts the number of methods that are EMCP (Equivalent Module Constant Pool).
+ int check_methods_and_mark_as_obsolete();
void transfer_old_native_function_registrations(instanceKlassHandle the_class);
// Install the redefinition of a class
--- a/hotspot/src/share/vm/runtime/arguments.hpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.hpp Wed Jul 05 20:01:44 2017 +0200
@@ -590,7 +590,9 @@
static void fix_appclasspath();
// Operation modi
- static Mode mode() { return _mode; }
+ static Mode mode() { return _mode; }
+ static bool is_interpreter_only() { return mode() == _int; }
+
// Utility: copies src into buf, replacing "%%" with "%" and "%p" with pid.
static bool copy_expand_pid(const char* src, size_t srclen, char* buf, size_t buflen);
--- a/hotspot/src/share/vm/runtime/globals.hpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 20:01:44 2017 +0200
@@ -2473,7 +2473,7 @@
develop(bool, CIPrintCompilerName, false, \
"when CIPrint is active, print the name of the active compiler") \
\
- develop(bool, CIPrintCompileQueue, false, \
+ diagnostic(bool, CIPrintCompileQueue, false, \
"display the contents of the compile queue whenever a " \
"compilation is enqueued") \
\
--- a/hotspot/src/share/vm/runtime/os.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/runtime/os.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -53,6 +53,7 @@
#include "runtime/vm_version.hpp"
#include "services/attachListener.hpp"
#include "services/nmtCommon.hpp"
+#include "services/mallocTracker.hpp"
#include "services/memTracker.hpp"
#include "services/threadService.hpp"
#include "utilities/defaultStream.hpp"
@@ -570,6 +571,17 @@
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
+#if INCLUDE_NMT
+ // NMT can not track malloc allocation size > MAX_MALLOC_SIZE, which is
+ // (1GB - 1) on 32-bit system. It is not an issue on 64-bit system, where
+ // MAX_MALLOC_SIZE = ((1 << 62) - 1).
+ // VM code does not have such large malloc allocation. However, it can come
+ // Unsafe call.
+ if (MemTracker::tracking_level() >= NMT_summary && size > MAX_MALLOC_SIZE) {
+ return NULL;
+ }
+#endif
+
#ifdef ASSERT
// checking for the WatcherThread and crash_protection first
// since os::malloc can be called when the libjvm.{dll,so} is
@@ -640,6 +652,13 @@
}
void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCallStack& stack) {
+#if INCLUDE_NMT
+ // See comments in os::malloc() above
+ if (MemTracker::tracking_level() >= NMT_summary && size > MAX_MALLOC_SIZE) {
+ return NULL;
+ }
+#endif
+
#ifndef ASSERT
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
--- a/hotspot/src/share/vm/runtime/os.hpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/runtime/os.hpp Wed Jul 05 20:01:44 2017 +0200
@@ -557,6 +557,16 @@
// Unload library
static void dll_unload(void *lib);
+ // Callback for loaded module information
+ // Input parameters:
+ // char* module_file_name,
+ // address module_base_addr,
+ // address module_top_addr,
+ // void* param
+ typedef int (*LoadedModulesCallbackFunc)(const char *, address, address, void *);
+
+ static int get_loaded_modules_info(LoadedModulesCallbackFunc callback, void *param);
+
// Return the handle of this process
static void* get_default_process_handle();
@@ -761,6 +771,9 @@
// Hook for os specific jvm options that we don't want to abort on seeing
static bool obsolete_option(const JavaVMOption *option);
+ // Amount beyond the callee frame size that we bang the stack.
+ static int extra_bang_size_in_bytes();
+
// Extensions
#include "runtime/os_ext.hpp"
--- a/hotspot/src/share/vm/runtime/sweeper.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/runtime/sweeper.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -618,7 +618,7 @@
if (mc == NULL) {
// Sometimes we can get here without MethodCounters. For example if we run with -Xcomp.
// Try to allocate them.
- mc = Method::build_method_counters(nm->method(), Thread::current());
+ mc = nm->method()->get_method_counters(Thread::current());
}
if (mc != NULL) {
// Snapshot the value as it's changed concurrently
--- a/hotspot/src/share/vm/runtime/vm_operations.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/runtime/vm_operations.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -470,3 +470,15 @@
ShouldNotReachHere();
}
}
+
+void VM_PrintCompileQueue::doit() {
+ CompileBroker::print_compile_queues(_out);
+}
+
+void VM_PrintCodeList::doit() {
+ CodeCache::print_codelist(_out);
+}
+
+void VM_PrintCodeCache::doit() {
+ CodeCache::print_layout(_out);
+}
--- a/hotspot/src/share/vm/runtime/vm_operations.hpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/runtime/vm_operations.hpp Wed Jul 05 20:01:44 2017 +0200
@@ -99,6 +99,9 @@
template(RotateGCLog) \
template(WhiteBoxOperation) \
template(ClassLoaderStatsOperation) \
+ template(PrintCompileQueue) \
+ template(PrintCodeList) \
+ template(PrintCodeCache) \
class VM_Operation: public CHeapObj<mtInternal> {
public:
@@ -413,4 +416,35 @@
void doit() { gclog_or_tty->rotate_log(true, _out); }
};
+class VM_PrintCompileQueue: public VM_Operation {
+ private:
+ outputStream* _out;
+
+ public:
+ VM_PrintCompileQueue(outputStream* st) : _out(st) {}
+ VMOp_Type type() const { return VMOp_PrintCompileQueue; }
+ void doit();
+};
+
+class VM_PrintCodeList: public VM_Operation {
+ private:
+ outputStream* _out;
+
+ public:
+ VM_PrintCodeList(outputStream* st) : _out(st) {}
+ VMOp_Type type() const { return VMOp_PrintCodeList; }
+ void doit();
+};
+
+class VM_PrintCodeCache: public VM_Operation {
+ private:
+ outputStream* _out;
+
+ public:
+ VM_PrintCodeCache(outputStream* st) : _out(st) {}
+ VMOp_Type type() const { return VMOp_PrintCodeCache; }
+ void doit();
+};
+
+
#endif // SHARE_VM_RUNTIME_VM_OPERATIONS_HPP
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp Wed Jul 05 20:01:44 2017 +0200
@@ -60,6 +60,9 @@
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(full_export, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RotateGCLogDCmd>(full_export, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassLoaderStatsDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompileQueueDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeListDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeCacheDCmd>(full_export, true, false));
// Enhanced JMX Agent Support
// These commands won't be exported via the DiagnosticCommandMBean until an
@@ -674,3 +677,18 @@
}
}
+void CompileQueueDCmd::execute(DCmdSource source, TRAPS) {
+ VM_PrintCompileQueue printCompileQueueOp(output());
+ VMThread::execute(&printCompileQueueOp);
+}
+
+void CodeListDCmd::execute(DCmdSource source, TRAPS) {
+ VM_PrintCodeList printCodeListOp(output());
+ VMThread::execute(&printCodeListOp);
+}
+
+void CodeCacheDCmd::execute(DCmdSource source, TRAPS) {
+ VM_PrintCodeCache printCodeCacheOp(output());
+ VMThread::execute(&printCodeCacheOp);
+}
+
--- a/hotspot/src/share/vm/services/diagnosticCommand.hpp Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp Wed Jul 05 20:01:44 2017 +0200
@@ -399,4 +399,68 @@
}
};
+class CompileQueueDCmd : public DCmd {
+public:
+ CompileQueueDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+ static const char* name() {
+ return "Compiler.queue";
+ }
+ static const char* description() {
+ return "Print methods queued for compilation.";
+ }
+ static const char* impact() {
+ return "Low";
+ }
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.lang.management.ManagementPermission",
+ "monitor", NULL};
+ return p;
+ }
+ static int num_arguments() { return 0; }
+ virtual void execute(DCmdSource source, TRAPS);
+};
+
+class CodeListDCmd : public DCmd {
+public:
+ CodeListDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+ static const char* name() {
+ return "Compiler.codelist";
+ }
+ static const char* description() {
+ return "Print all compiled methods in code cache.";
+ }
+ static const char* impact() {
+ return "Medium";
+ }
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.lang.management.ManagementPermission",
+ "monitor", NULL};
+ return p;
+ }
+ static int num_arguments() { return 0; }
+ virtual void execute(DCmdSource source, TRAPS);
+};
+
+
+class CodeCacheDCmd : public DCmd {
+public:
+ CodeCacheDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+ static const char* name() {
+ return "Compiler.codecache";
+ }
+ static const char* description() {
+ return "Print code cache layout and bounds.";
+ }
+ static const char* impact() {
+ return "Low";
+ }
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.lang.management.ManagementPermission",
+ "monitor", NULL};
+ return p;
+ }
+ static int num_arguments() { return 0; }
+ virtual void execute(DCmdSource source, TRAPS);
+};
+
#endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
--- a/hotspot/test/TEST.groups Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/test/TEST.groups Wed Jul 05 20:01:44 2017 +0200
@@ -80,6 +80,7 @@
runtime/NMT/MallocSiteHashOverflow.java \
runtime/NMT/MallocStressTest.java \
runtime/NMT/MallocTestType.java \
+ runtime/NMT/MallocTrackingVerify.java \
runtime/NMT/ReleaseCommittedMemory.java \
runtime/NMT/ReleaseNoCommit.java \
runtime/NMT/ShutdownTwice.java \
@@ -87,6 +88,7 @@
runtime/NMT/SummarySanityCheck.java \
runtime/NMT/ThreadedMallocTestType.java \
runtime/NMT/ThreadedVirtualAllocTestType.java \
+ runtime/NMT/UnsafeMallocLimit.java \
runtime/NMT/VirtualAllocCommitUncommitRecommit.java \
runtime/NMT/VirtualAllocTestType.java \
runtime/RedefineObject/TestRedefineObject.java \
--- a/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java Wed Jul 05 20:01:44 2017 +0200
@@ -22,7 +22,7 @@
*/
/*
- * @ignore 8027915
+ * @ignore 8049864
* @test TestParallelHeapSizeFlags
* @key gc
* @bug 8006088
--- a/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java Wed Jul 05 20:01:44 2017 +0200
@@ -22,7 +22,6 @@
*/
/*
- * @ignore 8025645
* @test TestUseCompressedOopsErgo
* @key gc
* @bug 8010722
--- a/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java Wed Jul 05 20:01:44 2017 +0200
@@ -22,7 +22,7 @@
*/
/**
- * @ignore 8042051
+ * @ignore 8019361
* @test TestDynShrinkHeap
* @bug 8016479
* @summary Verify that the heap shrinks after full GC according to the current values of the Min/MaxHeapFreeRatio flags
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/NMT/MallocTrackingVerify.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2014, 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 8054836
+ * @summary Test to verify correctness of malloc tracking
+ * @key nmt jcmd
+ * @library /testlibrary /testlibrary/whitebox
+ * @build MallocTrackingVerify
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocTrackingVerify
+ *
+ */
+
+import java.util.ArrayList;
+import java.util.Random;
+
+import com.oracle.java.testlibrary.*;
+
+import sun.hotspot.WhiteBox;
+
+public class MallocTrackingVerify {
+ private static int MAX_ALLOC = 4 * 1024;
+
+ static ArrayList<MallocMemory> mallocd_memory = new ArrayList<MallocMemory>();
+ static long mallocd_total = 0;
+ public static WhiteBox wb = WhiteBox.getWhiteBox();
+
+ public static void main(String args[]) throws Exception {
+ OutputAnalyzer output;
+
+ // Grab my own PID
+ String pid = Integer.toString(ProcessTools.getProcessId());
+ ProcessBuilder pb = new ProcessBuilder();
+
+ Random random = new Random();
+ // Allocate small amounts of memory with random pseudo call stack
+ while (mallocd_total < MAX_ALLOC) {
+ int size = random.nextInt(31) + 1;
+ long addr = wb.NMTMallocWithPseudoStack(size, random.nextInt());
+ if (addr != 0) {
+ MallocMemory mem = new MallocMemory(addr, size);
+ mallocd_memory.add(mem);
+ mallocd_total += size;
+ } else {
+ System.out.println("Out of malloc memory");
+ break;
+ }
+ }
+
+ pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary" });
+ output = new OutputAnalyzer(pb.start());
+ output.shouldContain("Test (reserved=4KB, committed=4KB)");
+
+ // Free
+ for (MallocMemory mem : mallocd_memory) {
+ wb.NMTFree(mem.addr());
+ }
+
+ // Run 'jcmd <pid> VM.native_memory summary', check for expected output
+ pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid,
+ "VM.native_memory", "summary" });
+ output = new OutputAnalyzer(pb.start());
+ output.shouldNotContain("Test (reserved=");
+ }
+
+ static class MallocMemory {
+ private long addr;
+ private int size;
+
+ MallocMemory(long addr, int size) {
+ this.addr = addr;
+ this.size = size;
+ }
+
+ long addr() {
+ return this.addr;
+ }
+
+ int size() {
+ return this.size;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/NMT/UnsafeMallocLimit.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, 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 8055289
+ * @library /testlibrary
+ * @build UnsafeMallocLimit
+ * @run main/othervm -Xmx32m -XX:NativeMemoryTracking=summary UnsafeMallocLimit
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+
+public class UnsafeMallocLimit {
+
+ public static void main(String args[]) throws Exception {
+ if (Platform.is32bit()) {
+ Unsafe unsafe = Utils.getUnsafe();
+ try {
+ unsafe.allocateMemory(1 << 30);
+ throw new RuntimeException("Did not get expected OOME");
+ } catch (OutOfMemoryError e) {
+ // Expected exception
+ }
+ } else {
+ System.out.println("Test only valid on 32-bit platforms");
+ }
+ }
+}
--- a/hotspot/test/runtime/RedefineFinalizer/RedefineFinalizer.java Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2014, 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 6904403
- * @summary Don't assert if we redefine finalize method
- * @library /testlibrary
- * @build RedefineClassHelper
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar RedefineFinalizer
- */
-
-/*
- * Regression test for hitting:
- *
- * assert(f == k->has_finalizer()) failed: inconsistent has_finalizer
- *
- * when redefining finalizer method
- */
-public class RedefineFinalizer {
-
- public static String newB =
- "class RedefineFinalizer$B {" +
- " protected void finalize() { " +
- " System.out.println(\"Finalizer called\");" +
- " }" +
- "}";
-
- public static void main(String[] args) throws Exception {
- RedefineClassHelper.redefineClass(B.class, newB);
-
- A a = new A();
- }
-
- static class A extends B {
- }
-
- static class B {
- protected void finalize() {
- // should be empty
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/RedefineTests/RedefineFinalizer.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, 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 6904403
+ * @summary Don't assert if we redefine finalize method
+ * @library /testlibrary
+ * @build RedefineClassHelper
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar RedefineFinalizer
+ */
+
+/*
+ * Regression test for hitting:
+ *
+ * assert(f == k->has_finalizer()) failed: inconsistent has_finalizer
+ *
+ * when redefining finalizer method
+ */
+public class RedefineFinalizer {
+
+ public static String newB =
+ "class RedefineFinalizer$B {" +
+ " protected void finalize() { " +
+ " System.out.println(\"Finalizer called\");" +
+ " }" +
+ "}";
+
+ public static void main(String[] args) throws Exception {
+ RedefineClassHelper.redefineClass(B.class, newB);
+
+ A a = new A();
+ }
+
+ static class A extends B {
+ }
+
+ static class B {
+ protected void finalize() {
+ // should be empty
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/RedefineTests/RedefineRunningMethods.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2014, 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 8055008
+ * @summary Redefine EMCP and non-EMCP methods that are running in an infinite loop
+ * @library /testlibrary
+ * @build RedefineClassHelper
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar -XX:TraceRedefineClasses=0x600 RedefineRunningMethods
+ */
+public class RedefineRunningMethods {
+
+ public static String newB =
+ "class RedefineRunningMethods$B {" +
+ " static int count1 = 0;" +
+ " static int count2 = 0;" +
+ " public static volatile boolean stop = false;" +
+ " static void localSleep() { " +
+ " try{ " +
+ " Thread.currentThread().sleep(10);" +
+ " } catch(InterruptedException ie) { " +
+ " } " +
+ " } " +
+ " public static void infinite() { " +
+ " System.out.println(\"infinite called\");" +
+ " }" +
+ " public static void infinite_emcp() { " +
+ " while (!stop) { count2++; localSleep(); }" +
+ " }" +
+ "}";
+
+ public static String evenNewerB =
+ "class RedefineRunningMethods$B {" +
+ " static int count1 = 0;" +
+ " static int count2 = 0;" +
+ " public static volatile boolean stop = false;" +
+ " static void localSleep() { " +
+ " try{ " +
+ " Thread.currentThread().sleep(1);" +
+ " } catch(InterruptedException ie) { " +
+ " } " +
+ " } " +
+ " public static void infinite() { }" +
+ " public static void infinite_emcp() { " +
+ " System.out.println(\"infinite_emcp now obsolete called\");" +
+ " }" +
+ "}";
+
+ static class B {
+ static int count1 = 0;
+ static int count2 = 0;
+ public static volatile boolean stop = false;
+ static void localSleep() {
+ try{
+ Thread.currentThread().sleep(10);//sleep for 10 ms
+ } catch(InterruptedException ie) {
+ }
+ }
+
+ public static void infinite() {
+ while (!stop) { count1++; localSleep(); }
+ }
+ public static void infinite_emcp() {
+ while (!stop) { count2++; localSleep(); }
+ }
+ }
+
+
+ public static void main(String[] args) throws Exception {
+
+ new Thread() {
+ public void run() {
+ B.infinite();
+ }
+ }.start();
+
+ new Thread() {
+ public void run() {
+ B.infinite_emcp();
+ }
+ }.start();
+
+ RedefineClassHelper.redefineClass(B.class, newB);
+
+ System.gc();
+
+ B.infinite();
+
+ // Start a thread with the second version of infinite_emcp running
+ new Thread() {
+ public void run() {
+ B.infinite_emcp();
+ }
+ }.start();
+
+ for (int i = 0; i < 20 ; i++) {
+ String s = new String("some garbage");
+ System.gc();
+ }
+
+ RedefineClassHelper.redefineClass(B.class, evenNewerB);
+ System.gc();
+
+ for (int i = 0; i < 20 ; i++) {
+ B.infinite();
+ String s = new String("some garbage");
+ System.gc();
+ }
+
+ B.infinite_emcp();
+
+ // purge should clean everything up.
+ B.stop = true;
+
+ for (int i = 0; i < 20 ; i++) {
+ B.infinite();
+ String s = new String("some garbage");
+ System.gc();
+ }
+ }
+}
--- a/hotspot/test/runtime/SharedArchiveFile/ArchiveDoesNotExist.java Thu Sep 18 13:27:06 2014 -0700
+++ b/hotspot/test/runtime/SharedArchiveFile/ArchiveDoesNotExist.java Wed Jul 05 20:01:44 2017 +0200
@@ -61,7 +61,7 @@
"-version");
output = new OutputAnalyzer(pb.start());
- output.shouldContain("java version");
+ output.shouldMatch("(java|openjdk) version");
output.shouldNotContain("sharing");
output.shouldHaveExitValue(0);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/CodeCacheTest.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2014, 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 CodeCacheTest
+ * @bug 8054889
+ * @build DcmdUtil CodeCacheTest
+ * @run main CodeCacheTest
+ * @summary Test of diagnostic command Compiler.codecache
+ */
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CodeCacheTest {
+
+ /**
+ * This test calls Jcmd (diagnostic command tool) Compiler.codecache and then parses the output,
+ * making sure that all number look ok
+ *
+ *
+ * Expected output:
+ *
+ * CodeCache: size=245760Kb used=4680Kb max_used=4680Kb free=241079Kb
+ * bounds [0x00007f5bd9000000, 0x00007f5bd94a0000, 0x00007f5be8000000]
+ * total_blobs=575 nmethods=69 adapters=423
+ * compilation: enabled
+ */
+
+ static Pattern line1 = Pattern.compile("CodeCache: size=(\\p{Digit}*)Kb used=(\\p{Digit}*)Kb max_used=(\\p{Digit}*)Kb free=(\\p{Digit}*)Kb");
+ static Pattern line2 = Pattern.compile(" bounds \\[0x(\\p{XDigit}*), 0x(\\p{XDigit}*), 0x(\\p{XDigit}*)\\]");
+ static Pattern line3 = Pattern.compile(" total_blobs=(\\p{Digit}*) nmethods=(\\p{Digit}*) adapters=(\\p{Digit}*)");
+ static Pattern line4 = Pattern.compile(" compilation: (\\w*)");
+
+ public static void main(String arg[]) throws Exception {
+
+ // Get output from dcmd (diagnostic command)
+ String result = DcmdUtil.executeDcmd("Compiler.codecache");
+ BufferedReader r = new BufferedReader(new StringReader(result));
+
+ // Validate first line
+ String line;
+ line = r.readLine();
+ Matcher m = line1.matcher(line);
+ if (m.matches()) {
+ for(int i = 1; i <= 4; i++) {
+ int val = Integer.parseInt(m.group(i));
+ if (val < 0) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ }
+ } else {
+ throw new Exception("Regexp 1 failed");
+ }
+
+ // Validate second line
+ line = r.readLine();
+ m = line2.matcher(line);
+ if (m.matches()) {
+ long start = Long.parseLong(m.group(1), 16);
+ if (start < 0) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ long mark = Long.parseLong(m.group(2), 16);
+ if (mark < 0) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ long top = Long.parseLong(m.group(3), 16);
+ if (top < 0) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ if (start > mark) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ if (mark > top) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ } else {
+ throw new Exception("Regexp 2 failed line: " + line);
+ }
+
+ // Validate third line
+ line = r.readLine();
+ m = line3.matcher(line);
+ if (m.matches()) {
+ int blobs = Integer.parseInt(m.group(1));
+ if (blobs <= 0) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ int nmethods = Integer.parseInt(m.group(2));
+ if (nmethods <= 0) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ int adapters = Integer.parseInt(m.group(3));
+ if (adapters <= 0) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ if (blobs < (nmethods + adapters)) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ } else {
+ throw new Exception("Regexp 3 failed");
+ }
+
+ // Validate fourth line
+ line = r.readLine();
+ m = line4.matcher(line);
+ if (m.matches()) {
+ if (!m.group(1).equals("enabled")) {
+ throw new Exception("Invalid message: '" + m.group(1) + "'");
+ }
+ } else {
+ throw new Exception("Regexp 4 failed");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/CodelistTest.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2014, 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 CodelistTest
+ * @bug 8054889
+ * @build DcmdUtil MethodIdentifierParser CodelistTest
+ * @run main CodelistTest
+ * @summary Test of diagnostic command Compiler.codelist
+ */
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+
+public class CodelistTest {
+
+ /**
+ * This test calls Jcmd (diagnostic command tool) Compiler.codelist and then parses the output,
+ * making sure that the first methods in the list is valid by reflection.
+ *
+ * Output example:
+ *
+ * 6 0 java.lang.System.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V [0x00007f7b49200910, 0x00007f7b49200aa0 - 0x00007f7b49200d30]
+ * 2 3 java.lang.String.indexOf(II)I [0x00007f7b49200d90, 0x00007f7b49200f60 - 0x00007f7b49201490]
+ * 7 3 java.lang.Math.min(II)I [0x00007f7b4922f010, 0x00007f7b4922f180 - 0x00007f7b4922f338]
+ * 8 3 java.lang.String.equals(Ljava/lang/Object;)Z [0x00007f7b4922fb10, 0x00007f7b4922fd40 - 0x00007f7b49230698]
+ * 9 3 java.lang.AbstractStringBuilder.ensureCapacityInternal(I)V [0x00007f7b49232010, 0x00007f7b492321a0 - 0x00007f7b49232510]
+ * 10 1 java.lang.Object.<init>()V [0x00007f7b49233e90, 0x00007f7b49233fe0 - 0x00007f7b49234118]
+ *
+ */
+
+ public static void main(String arg[]) throws Exception {
+ int ok = 0;
+ int fail = 0;
+
+ // Get output from dcmd (diagnostic command)
+ String result = DcmdUtil.executeDcmd("Compiler.codelist");
+ BufferedReader r = new BufferedReader(new StringReader(result));
+
+ // Grab a method name from the output
+ String line;
+ int count = 0;
+
+ while((line = r.readLine()) != null) {
+ count++;
+
+ String[] parts = line.split(" ");
+ // int compileID = Integer.parseInt(parts[0]);
+ // int compileLevel = Integer.parseInt(parts[1]);
+ String methodPrintedInLogFormat = parts[2];
+
+ // skip inits and clinits - they can not be reflected
+ if (methodPrintedInLogFormat.contains("<init>")) {
+ continue;
+ }
+ if (methodPrintedInLogFormat.contains("<clinit>")) {
+ continue;
+ }
+
+ MethodIdentifierParser mf = new MethodIdentifierParser(methodPrintedInLogFormat);
+ Method m;
+ try {
+ m = mf.getMethod();
+ } catch (NoSuchMethodException e) {
+ m = null;
+ }
+ if (m == null) {
+ throw new Exception("Test failed");
+ }
+ if (count > 10) {
+ // Testing 10 entries is enough. Lets not waste time.
+ break;
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/CompilerQueueTest.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014, 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 CompilerQueueTest
+ * @bug 8054889
+ * @build DcmdUtil CompilerQueueTest
+ * @run main CompilerQueueTest
+ * @summary Test of diagnostic command Compiler.queue
+ */
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+
+public class CompilerQueueTest {
+
+ /**
+ * This test calls Jcmd (diagnostic command tool) Compiler.queue and
+ * then parses the output, making sure that the output look ok.
+ *
+ *
+ * Output example:
+ *
+ * Contents of C1 compile queue
+ * ----------------------------
+ * 73 3 java.lang.AbstractStringBuilder::append (50 bytes)
+ * 74 1 java.util.TreeMap::size (5 bytes)
+ * 75 3 java.lang.StringBuilder::append (8 bytes)
+ * 83 3 java.util.TreeMap$ValueIterator::next (8 bytes)
+ * 84 1 javax.management.MBeanFeatureInfo::getName (5 bytes)
+ * ----------------------------
+ * Contents of C2 compile queue
+ * ----------------------------
+ * Empty
+ * ----------------------------
+ *
+ **/
+
+ public static void main(String arg[]) throws Exception {
+
+ // Get output from dcmd (diagnostic command)
+ String result = DcmdUtil.executeDcmd("Compiler.queue");
+ BufferedReader r = new BufferedReader(new StringReader(result));
+
+ String line;
+ match(r.readLine(), "Contents of C1 compile queue");
+ match(r.readLine(), "----------------------------");
+ String str = r.readLine();
+ if (!str.equals("Empty")) {
+ while (str.charAt(0) != '-') {
+ validateMethodLine(str);
+ str = r.readLine();
+ }
+ } else {
+ str = r.readLine();
+ }
+
+ match(str, "----------------------------");
+ match(r.readLine(), "Contents of C2 compile queue");
+ match(r.readLine(), "----------------------------");
+ str = r.readLine();
+ if (!str.equals("Empty")) {
+ while (str.charAt(0) != '-') {
+ validateMethodLine(str);
+ str = r.readLine();
+ }
+ } else {
+ str = r.readLine();
+ }
+ match(str, "----------------------------");
+ }
+
+ private static void validateMethodLine(String str) throws Exception {
+ String name = str.substring(19);
+ int sep = name.indexOf("::");
+ try {
+ Class.forName(name.substring(0, sep));
+ } catch (ClassNotFoundException e) {
+ throw new Exception("Failed parsing dcmd queue");
+ }
+ }
+
+ public static void match(String line, String str) throws Exception {
+ if (!line.equals(str)) {
+ throw new Exception("String equals: " + line + ", " + str);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/MethodIdentifierParser.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2014, 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.lang.reflect.Method;
+import java.util.ArrayList;
+
+public class MethodIdentifierParser {
+
+ private String logString;
+ private String className;
+ private String methodName;
+ private String methodDescriptor;
+
+ /**
+ * This is a utility class for parsing the log entries for a method. It supplies
+ * a few select methods for reflecting the class and method from that information.
+ *
+ * Example log entries:
+ * "java.util.TreeMap.successor(Ljava/util/TreeMap$Entry;)Ljava/util/TreeMap$Entry;"
+ */
+
+ public MethodIdentifierParser(String logString) {
+ this.logString = logString;
+
+ int i = logString.lastIndexOf("."); // find start of method name
+ className = logString.substring(0, i); // classname is everything before
+ int i2 = logString.indexOf("("); // Signature starts with an '('
+ methodName = logString.substring(i+1, i2);
+ methodDescriptor = logString.substring(i2, logString.length());
+
+ // Add sanity check for extracted fields
+ }
+
+ public Method getMethod() throws NoSuchMethodException, SecurityException, ClassNotFoundException, Exception {
+ try {
+ return Class.forName(className).getDeclaredMethod(methodName, getParamenterDescriptorArray());
+ } catch (UnexpectedTokenException e) {
+ throw new Exception("Parse failed");
+ }
+ }
+
+ public Class<?>[] getParamenterDescriptorArray() throws ClassNotFoundException, UnexpectedTokenException {
+ ParameterDecriptorIterator s = new ParameterDecriptorIterator(methodDescriptor);
+ Class<?> paramType;
+ ArrayList<Class<?>> list = new ArrayList<Class<?>>();
+ while ((paramType = s.nextParamType()) != null) {
+ list.add(paramType);
+ }
+ if (list.size() > 0) {
+ return list.toArray(new Class<?>[list.size()]);
+ } else {
+ return null;
+ }
+ }
+
+ class ParameterDecriptorIterator {
+
+ // This class uses charAt() indexing for startMark and i
+ // That is when i points to the last char it can be retrieved with
+ // charAt(i). Including the last char for a subString requires
+ // substring(startMark, i+1);
+
+ private String methodDescriptor;
+ private int startMark;
+
+ public ParameterDecriptorIterator(String signature) {
+ this.methodDescriptor = signature;
+ this.startMark = 0;
+ if (signature.charAt(0) == '(') {
+ this.startMark = 1;
+ }
+ }
+
+ public Class<?> nextParamType() throws UnexpectedTokenException {
+ int i = startMark;
+ while (methodDescriptor.length() > i) {
+ switch (methodDescriptor.charAt(i)) {
+ case 'C':
+ case 'B':
+ case 'I':
+ case 'J':
+ case 'Z':
+ case 'F':
+ case 'D':
+ case 'S':
+ // Primitive class case, but we may have gotten here with [ as first token
+ break;
+ case 'L':
+ // Internal class name suffixed by ';'
+ while (methodDescriptor.charAt(i) != ';') {
+ i++;
+ }
+ break;
+ case '[':
+ i++; // arrays -> do another pass
+ continue;
+ case ')':
+ return null; // end found
+ case 'V':
+ case ';':
+ default:
+ throw new UnexpectedTokenException(methodDescriptor, i);
+ }
+ break;
+ }
+ if (i == startMark) {
+ // Single char -> primitive class case
+ startMark++; // Update for next iteration
+ switch (methodDescriptor.charAt(i)) {
+ case 'C':
+ return char.class;
+ case 'B':
+ return byte.class;
+ case 'I':
+ return int.class;
+ case 'J':
+ return long.class;
+ case 'F':
+ return float.class;
+ case 'D':
+ return double.class;
+ case 'S':
+ return short.class;
+ case 'Z':
+ return boolean.class;
+ default:
+ throw new UnexpectedTokenException(methodDescriptor, i);
+ }
+ } else {
+ // Multi char case
+ String nextParam;
+ if (methodDescriptor.charAt(startMark) == 'L') {
+ // When reflecting a class the leading 'L' and trailing';' must be removed.
+ // (When reflecting an array of classes, they must remain...)
+ nextParam = methodDescriptor.substring(startMark+1, i);
+ } else {
+ // Any kind of array - simple case, use whole descriptor when reflecting.
+ nextParam = methodDescriptor.substring(startMark, i+1);
+ }
+ startMark = ++i; // Update for next iteration
+ try {
+ // The parameter descriptor uses JVM internal class identifier with '/' as
+ // package separator, but Class.forName expects '.'.
+ nextParam = nextParam.replace('/', '.');
+ return Class.forName(nextParam);
+ } catch (ClassNotFoundException e) {
+ System.out.println("Class not Found: " + nextParam);
+ return null;
+ }
+ }
+ }
+ }
+
+ class UnexpectedTokenException extends Exception {
+ String descriptor;
+ int i;
+ public UnexpectedTokenException(String descriptor, int i) {
+ this.descriptor = descriptor;
+ this.i = i;
+ }
+
+ @Override
+ public String toString() {
+ return "Unexpected token at: " + i + " in signature: " + descriptor;
+ }
+
+ private static final long serialVersionUID = 1L;
+ }
+
+ public void debugPrint() {
+ System.out.println("mlf in: " + logString);
+ System.out.println("mlf class: " + className);
+ System.out.println("mlf method: " + methodName);
+ System.out.println("mlf methodDescriptor: " + methodDescriptor);
+ }
+}
--- a/jaxp/.hgtags Thu Sep 18 13:27:06 2014 -0700
+++ b/jaxp/.hgtags Wed Jul 05 20:01:44 2017 +0200
@@ -273,3 +273,4 @@
dc1e26434b3fd7e9b8eeab149103c1e30965f95c jdk9-b28
30adcd13a313ea91e81164801a2f89282756d933 jdk9-b29
d181d4002214e4914d5525bd5ee13369311c765c jdk9-b30
+292317ebc7dbaca6b3965f0bc7b38a2cee733b7a jdk9-b31
--- a/jdk/.hgtags Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/.hgtags Wed Jul 05 20:01:44 2017 +0200
@@ -273,3 +273,4 @@
1828f73b35cfe35e460e41fd6e087ab1f83e0621 jdk9-b28
2da27e8e2c865e154f0c2eb9009f011a44649b11 jdk9-b29
8d24fb4493f13d380a2adf62d444e1e5a4451f37 jdk9-b30
+71e99dae28f9791287b88d46e16a266b564f22be jdk9-b31
--- a/jdk/make/CreateJars.gmk Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/make/CreateJars.gmk Wed Jul 05 20:01:44 2017 +0200
@@ -220,7 +220,6 @@
sun/tools/serialver \
sun/tools/tree \
sun/tools/util \
- sun/util/cldr/CLDRLocaleDataMetaInfo.class \
sun/util/resources/provider/NonEnLocaleDataMetaInfo.class \
META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo \
sun/util/resources/cldr \
@@ -452,11 +451,9 @@
$(eval $(call SetupArchive,BUILD_CLDRDATA_JAR, \
$(CLDR_METAINF_SERVICES), \
SRCS := $(JDK_OUTPUTDIR)/modules/jdk.localedata \
- $(JDK_OUTPUTDIR)/modules/java.base \
$(CLDR_SERVICES_DIR), \
SUFFIXES := .class, \
INCLUDES := sun/text/resources/cldr \
- sun/util/cldr/CLDRLocaleDataMetaInfo.class \
sun/util/resources/cldr, \
EXTRA_FILES := META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo, \
JAR := $(CLDRDATA_JAR_DST), \
--- a/jdk/make/gensrc/Gensrc-java.base.gmk Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/make/gensrc/Gensrc-java.base.gmk Wed Jul 05 20:01:44 2017 +0200
@@ -29,14 +29,13 @@
include GensrcProperties.gmk
GENSRC_JAVA_BASE += $(GENSRC_PROPERTIES)
-include GensrcLocaleDataMetaInfo.gmk
+include GensrcLocaleData.gmk
include GensrcCharacterData.gmk
include GensrcMisc.gmk
include GensrcCharsetMapping.gmk
include GensrcCharsetCoder.gmk
include GensrcBuffer.gmk
include GensrcExceptions.gmk
-include GensrcCLDR.gmk
java.base: $(GENSRC_JAVA_BASE)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/gensrc/Gensrc-jdk.localedata.gmk Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2014, 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.
+#
+
+include GensrcCommon.gmk
+
+# Hook to include the corresponding custom file, if present.
+$(eval $(call IncludeCustomExtension, jdk, gensrc/Gensrc-jdk.localedata.gmk))
+
+include GensrcLocaleData.gmk
+include GensrcCLDR.gmk
+
+jdk.localedata: $(GENSRC_JDK_LOCALEDATA)
+
+all: jdk.localedata
+
+.PHONY: all jdk.localedata
--- a/jdk/make/gensrc/GensrcCLDR.gmk Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/make/gensrc/GensrcCLDR.gmk Wed Jul 05 20:01:44 2017 +0200
@@ -27,9 +27,8 @@
CLDRSRCDIR := $(JDK_TOPDIR)/src/jdk.localedata/share/classes/sun/util/cldr/resources/$(subst .,_,$(CLDRVERSION))
GENSRC_DIR := $(JDK_OUTPUTDIR)/gensrc/jdk.localedata
-BASE_GENSRC_DIR := $(JDK_OUTPUTDIR)/gensrc/java.base
-CLDR_METAINFO_FILE := $(BASE_GENSRC_DIR)/sun/util/cldr/CLDRLocaleDataMetaInfo.java
+CLDR_METAINFO_FILE := $(GENSRC_DIR)/sun/util/resources/cldr/provider/CLDRLocaleDataMetaInfo.java
$(CLDR_METAINFO_FILE): $(wildcard $(CLDRSRCDIR)/common/dtd/*.dtd) \
$(wildcard $(CLDRSRCDIR)/common/main/*.xml) \
@@ -37,16 +36,6 @@
$(BUILD_TOOLS_JDK)
$(MKDIR) -p $(GENSRC_DIR)
$(TOOL_CLDRCONVERTER) -base $(CLDRSRCDIR) -o $(GENSRC_DIR)
- $(MKDIR) -p $(BASE_GENSRC_DIR)/sun/text/resources/cldr
- $(MKDIR) -p $(BASE_GENSRC_DIR)/sun/util/resources/cldr
- $(RM) -r $(BASE_GENSRC_DIR)/sun/text/resources/cldr/en \
- $(BASE_GENSRC_DIR)/sun/util/resources/cldr/en
- $(MV) $(GENSRC_DIR)/sun/text/resources/cldr/en $(BASE_GENSRC_DIR)/sun/text/resources/cldr/en
- $(MV) $(GENSRC_DIR)/sun/util/resources/cldr/en $(BASE_GENSRC_DIR)/sun/util/resources/cldr/en
- $(MV) $(GENSRC_DIR)/sun/text/resources/cldr/*.java $(BASE_GENSRC_DIR)/sun/text/resources/cldr
- $(MV) $(GENSRC_DIR)/sun/util/resources/cldr/*.java $(BASE_GENSRC_DIR)/sun/util/resources/cldr
- $(MKDIR) -p $(@D)
- $(MV) $(GENSRC_DIR)/sun/util/cldr/CLDRLocaleDataMetaInfo.java $@
GENSRC_CLDR := $(CLDR_METAINFO_FILE)
-GENSRC_JAVA_BASE += $(GENSRC_CLDR)
+GENSRC_JDK_LOCALEDATA += $(GENSRC_CLDR)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/gensrc/GensrcLocaleData.gmk Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,152 @@
+#
+# Copyright (c) 2011, 2014, 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.
+#
+
+# Scan for all locale resources and extract for which locales there exists
+# resources. Then put this meta information about existing (supported?) locales
+# into LocaleDataMetaInfo.java
+
+# First go look for all locale files
+LOCALE_FILES := $(shell $(FIND) $(JDK_TOPDIR)/src/java.base/share/classes \
+ $(JDK_TOPDIR)/src/jdk.localedata/share/classes \
+ -name "FormatData_*.java" -o -name "FormatData_*.properties" -o \
+ -name "CollationData_*.java" -o -name "CollationData_*.properties" -o \
+ -name "TimeZoneNames_*.java" -o -name "TimeZoneNames_*.properties" -o \
+ -name "LocaleNames_*.java" -o -name "LocaleNames_*.properties" -o \
+ -name "CurrencyNames_*.java" -o -name "CurrencyNames_*.properties" -o \
+ -name "CalendarData_*.java" -o -name "CalendarData_*.properties" -o \
+ -name "BreakIteratorInfo_*.java" -o -name "BreakIteratorRules_*.java")
+
+# Then translate the locale files into for example: FormatData_sv
+LOCALE_RESOURCES := $(sort $(subst .properties,,$(subst .java,,$(notdir $(LOCALE_FILES)))))
+
+# Include the list of resources found during the previous compile.
+-include $(JDK_OUTPUTDIR)/gensrc/_the.locale_resources
+
+MISSING_RESOURCES := $(filter-out $(LOCALE_RESOURCES), $(PREV_LOCALE_RESOURCES))
+NEW_RESOURCES := $(filter-out $(PREV_LOCALE_RESOURCES), $(LOCALE_RESOURCES))
+
+ifneq (, $(MISSING_RESOURCES)$(NEW_RESOURCES))
+ # There is a difference in the number of supported resources. Trigger a regeneration.
+ $(shell $(RM) $(JDK_OUTPUTDIR)/gensrc/sun/util/locale/provider/LocaleDataMetaInfo.java)
+endif
+
+# The EN locales
+EN_LOCALES := en%
+
+# Locales that don't have any resource files should be included here.
+ALL_NON_EN_LOCALES := ja-JP-JP nb-NO nn-NO th-TH-TH
+
+SED_ENARGS := -e 's|$(HASH)warn This file is preprocessed before being compiled|// -- This file was mechanically generated: Do not edit! -- //|g'
+SED_NONENARGS := $(SED_ENARGS)
+
+# Fill in the languages and package names
+SED_ENARGS += -e 's/$(HASH)Lang$(HASH)/En/' \
+ -e 's/$(HASH)Package$(HASH)/sun.util.locale.provider/'
+SED_NONENARGS += -e 's/$(HASH)Lang$(HASH)/NonEn/' \
+ -e 's/$(HASH)Package$(HASH)/sun.util.resources.provider/'
+
+# This macro creates a sed expression that substitues for example:
+# #FormatData_ENLocales# with: en% locales.
+define CaptureLocale
+ $1_LOCALES := $$(subst _,-,$$(filter-out $1, $$(subst $1_,,$$(filter $1_%, $(LOCALE_RESOURCES)))))
+ $1_EN_LOCALES := $$(filter $(EN_LOCALES), $$($1_LOCALES))
+ $1_NON_EN_LOCALES := $$(filter-out $(EN_LOCALES), $$($1_LOCALES))
+
+ # Special handling for Chinese locales to include implicit scripts
+ $1_NON_EN_LOCALES := $$(subst zh-CN,zh-CN$$(SPACE)zh-Hans-CN, $$($1_NON_EN_LOCALES))
+ $1_NON_EN_LOCALES := $$(subst zh-SG,zh-SG$$(SPACE)zh-Hans-SG, $$($1_NON_EN_LOCALES))
+ $1_NON_EN_LOCALES := $$(subst zh-HK,zh-HK$$(SPACE)zh-Hant-HK, $$($1_NON_EN_LOCALES))
+ $1_NON_EN_LOCALES := $$(subst zh-MO,zh-MO$$(SPACE)zh-Hant-MO, $$($1_NON_EN_LOCALES))
+ $1_NON_EN_LOCALES := $$(subst zh-TW,zh-TW$$(SPACE)zh-Hant-TW, $$($1_NON_EN_LOCALES))
+
+ ALL_EN_LOCALES += $$($1_EN_LOCALES)
+ ALL_NON_EN_LOCALES += $$($1_NON_EN_LOCALES)
+
+ # Don't sed in a space if there are no locales.
+ SED_ENARGS += -e 's/$$(HASH)$1_Locales$$(HASH)/$$(if $$($1_EN_LOCALES),$$(SPACE)$$($1_EN_LOCALES),)/g'
+ SED_NONENARGS += -e 's/$$(HASH)$1_Locales$$(HASH)/$$(if $$($1_NON_EN_LOCALES),$$(SPACE)$$($1_NON_EN_LOCALES),)/g'
+endef
+
+#sun.text.resources.FormatData
+$(eval $(call CaptureLocale,FormatData))
+
+#sun.text.resources.CollationData
+$(eval $(call CaptureLocale,CollationData))
+
+#sun.text.resources.BreakIteratorInfo
+$(eval $(call CaptureLocale,BreakIteratorInfo))
+
+#sun.text.resources.BreakIteratorRules
+$(eval $(call CaptureLocale,BreakIteratorRules))
+
+#sun.util.resources.TimeZoneNames
+$(eval $(call CaptureLocale,TimeZoneNames))
+
+#sun.util.resources.LocaleNames
+$(eval $(call CaptureLocale,LocaleNames))
+
+#sun.util.resources.CurrencyNames
+$(eval $(call CaptureLocale,CurrencyNames))
+
+#sun.util.resources.CalendarData
+$(eval $(call CaptureLocale,CalendarData))
+
+SED_ENARGS += -e 's/$(HASH)AvailableLocales_Locales$(HASH)/$(sort $(ALL_EN_LOCALES))/g'
+SED_NONENARGS += -e 's/$(HASH)AvailableLocales_Locales$(HASH)/$(sort $(ALL_NON_EN_LOCALES))/g'
+
+$(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/EnLocaleDataMetaInfo.java: \
+ $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template
+ $(MKDIR) -p $(@D)
+ $(ECHO) Creating sun/util/locale/provider/EnLocaleDataMetaInfo.java from $(words $(LOCALE_RESOURCES)) found resources.
+ $(PRINTF) "PREV_LOCALE_RESOURCES:=$(LOCALE_RESOURCES)" > $(JDK_OUTPUTDIR)/gensrc/_the.locale_resources
+ $(SED) $(SED_ENARGS) $< > $@
+
+$(JDK_OUTPUTDIR)/gensrc/jdk.localedata/sun/util/resources/provider/NonEnLocaleDataMetaInfo.java: \
+ $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template
+ $(MKDIR) -p $(@D)
+ $(ECHO) Creating sun/util/resources/provider/NonEnLocaleDataMetaInfo.java from $(words $(LOCALE_RESOURCES)) found resources.
+ $(PRINTF) "PREV_LOCALE_RESOURCES:=$(LOCALE_RESOURCES)" > $(JDK_OUTPUTDIR)/gensrc/_the.locale_resources
+ $(SED) $(SED_NONENARGS) $< > $@
+
+GENSRC_BASELOCALEDATA := $(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/EnLocaleDataMetaInfo.java
+GENSRC_LOCALEDATA := $(JDK_OUTPUTDIR)/gensrc/jdk.localedata/sun/util/resources/provider/NonEnLocaleDataMetaInfo.java
+
+################################################################################
+
+GENSRC_CRBC_DST := $(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/CoreResourceBundleControl.java
+GENSRC_CRBC_CMD := $(JDK_TOPDIR)/make/scripts/localelist.sh
+
+JRE_NONEXIST_LOCALES := en en_US de_DE es_ES fr_FR it_IT ja_JP ko_KR sv_SE zh
+
+$(GENSRC_CRBC_DST): $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/CoreResourceBundleControl-XLocales.java.template \
+ $(GENSRC_CRBC_CMD)
+ $(MKDIR) -p $(@D)
+ NAWK="$(NAWK)" SED="$(SED)" $(SH) $(GENSRC_CRBC_CMD) "$(JRE_NONEXIST_LOCALES)" $< $@
+
+GENSRC_BASELOCALEDATA += $(GENSRC_CRBC_DST)
+GENSRC_JAVA_BASE += $(GENSRC_BASELOCALEDATA)
+GENSRC_JDK_LOCALEDATA += $(GENSRC_LOCALEDATA)
+
+################################################################################
--- a/jdk/make/gensrc/GensrcLocaleDataMetaInfo.gmk Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,151 +0,0 @@
-#
-# Copyright (c) 2011, 2014, 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.
-#
-
-# Scan for all locale resources and extract for which locales there exists
-# resources. Then put this meta information about existing (supported?) locales
-# into LocaleDataMetaInfo.java
-
-# First go look for all locale files
-LOCALE_FILES := $(shell $(FIND) $(JDK_TOPDIR)/src/java.base/share/classes \
- $(JDK_TOPDIR)/src/jdk.localedata/share/classes \
- -name "FormatData_*.java" -o -name "FormatData_*.properties" -o \
- -name "CollationData_*.java" -o -name "CollationData_*.properties" -o \
- -name "TimeZoneNames_*.java" -o -name "TimeZoneNames_*.properties" -o \
- -name "LocaleNames_*.java" -o -name "LocaleNames_*.properties" -o \
- -name "CurrencyNames_*.java" -o -name "CurrencyNames_*.properties" -o \
- -name "CalendarData_*.java" -o -name "CalendarData_*.properties" -o \
- -name "BreakIteratorInfo_*.java" -o -name "BreakIteratorRules_*.java")
-
-# Then translate the locale files into for example: FormatData_sv
-LOCALE_RESOURCES := $(sort $(subst .properties,,$(subst .java,,$(notdir $(LOCALE_FILES)))))
-
-# Include the list of resources found during the previous compile.
--include $(JDK_OUTPUTDIR)/gensrc/_the.locale_resources
-
-MISSING_RESOURCES := $(filter-out $(LOCALE_RESOURCES), $(PREV_LOCALE_RESOURCES))
-NEW_RESOURCES := $(filter-out $(PREV_LOCALE_RESOURCES), $(LOCALE_RESOURCES))
-
-ifneq (, $(MISSING_RESOURCES)$(NEW_RESOURCES))
- # There is a difference in the number of supported resources. Trigger a regeneration.
- $(shell $(RM) $(JDK_OUTPUTDIR)/gensrc/sun/util/locale/provider/LocaleDataMetaInfo.java)
-endif
-
-# The EN locales
-EN_LOCALES := en%
-
-# Locales that don't have any resource files should be included here.
-ALL_NON_EN_LOCALES := ja-JP-JP nb-NO nn-NO th-TH-TH
-
-SED_ENARGS := -e 's|$(HASH)warn This file is preprocessed before being compiled|// -- This file was mechanically generated: Do not edit! -- //|g'
-SED_NONENARGS := $(SED_ENARGS)
-
-# Fill in the languages and package names
-SED_ENARGS += -e 's/$(HASH)Lang$(HASH)/En/' \
- -e 's/$(HASH)Package$(HASH)/sun.util.locale.provider/'
-SED_NONENARGS += -e 's/$(HASH)Lang$(HASH)/NonEn/' \
- -e 's/$(HASH)Package$(HASH)/sun.util.resources.provider/'
-
-# This macro creates a sed expression that substitues for example:
-# #FormatData_ENLocales# with: en% locales.
-define CaptureLocale
- $1_LOCALES := $$(subst _,-,$$(filter-out $1, $$(subst $1_,,$$(filter $1_%, $(LOCALE_RESOURCES)))))
- $1_EN_LOCALES := $$(filter $(EN_LOCALES), $$($1_LOCALES))
- $1_NON_EN_LOCALES := $$(filter-out $(EN_LOCALES), $$($1_LOCALES))
-
- # Special handling for Chinese locales to include implicit scripts
- $1_NON_EN_LOCALES := $$(subst zh-CN,zh-CN$$(SPACE)zh-Hans-CN, $$($1_NON_EN_LOCALES))
- $1_NON_EN_LOCALES := $$(subst zh-SG,zh-SG$$(SPACE)zh-Hans-SG, $$($1_NON_EN_LOCALES))
- $1_NON_EN_LOCALES := $$(subst zh-HK,zh-HK$$(SPACE)zh-Hant-HK, $$($1_NON_EN_LOCALES))
- $1_NON_EN_LOCALES := $$(subst zh-MO,zh-MO$$(SPACE)zh-Hant-MO, $$($1_NON_EN_LOCALES))
- $1_NON_EN_LOCALES := $$(subst zh-TW,zh-TW$$(SPACE)zh-Hant-TW, $$($1_NON_EN_LOCALES))
-
- ALL_EN_LOCALES += $$($1_EN_LOCALES)
- ALL_NON_EN_LOCALES += $$($1_NON_EN_LOCALES)
-
- # Don't sed in a space if there are no locales.
- SED_ENARGS += -e 's/$$(HASH)$1_Locales$$(HASH)/$$(if $$($1_EN_LOCALES),$$(SPACE)$$($1_EN_LOCALES),)/g'
- SED_NONENARGS += -e 's/$$(HASH)$1_Locales$$(HASH)/$$(if $$($1_NON_EN_LOCALES),$$(SPACE)$$($1_NON_EN_LOCALES),)/g'
-endef
-
-#sun.text.resources.FormatData
-$(eval $(call CaptureLocale,FormatData))
-
-#sun.text.resources.CollationData
-$(eval $(call CaptureLocale,CollationData))
-
-#sun.text.resources.BreakIteratorInfo
-$(eval $(call CaptureLocale,BreakIteratorInfo))
-
-#sun.text.resources.BreakIteratorRules
-$(eval $(call CaptureLocale,BreakIteratorRules))
-
-#sun.util.resources.TimeZoneNames
-$(eval $(call CaptureLocale,TimeZoneNames))
-
-#sun.util.resources.LocaleNames
-$(eval $(call CaptureLocale,LocaleNames))
-
-#sun.util.resources.CurrencyNames
-$(eval $(call CaptureLocale,CurrencyNames))
-
-#sun.util.resources.CalendarData
-$(eval $(call CaptureLocale,CalendarData))
-
-SED_ENARGS += -e 's/$(HASH)AvailableLocales_Locales$(HASH)/$(sort $(ALL_EN_LOCALES))/g'
-SED_NONENARGS += -e 's/$(HASH)AvailableLocales_Locales$(HASH)/$(sort $(ALL_NON_EN_LOCALES))/g'
-
-$(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/EnLocaleDataMetaInfo.java: \
- $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template
- $(MKDIR) -p $(@D)
- $(ECHO) Creating sun/util/locale/provider/EnLocaleDataMetaInfo.java from $(words $(LOCALE_RESOURCES)) found resources.
- $(PRINTF) "PREV_LOCALE_RESOURCES:=$(LOCALE_RESOURCES)" > $(JDK_OUTPUTDIR)/gensrc/_the.locale_resources
- $(SED) $(SED_ENARGS) $< > $@
-
-$(JDK_OUTPUTDIR)/gensrc/jdk.localedata/sun/util/resources/provider/NonEnLocaleDataMetaInfo.java: \
- $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template
- $(MKDIR) -p $(@D)
- $(ECHO) Creating sun/util/resources/provider/NonEnLocaleDataMetaInfo.java from $(words $(LOCALE_RESOURCES)) found resources.
- $(PRINTF) "PREV_LOCALE_RESOURCES:=$(LOCALE_RESOURCES)" > $(JDK_OUTPUTDIR)/gensrc/_the.locale_resources
- $(SED) $(SED_NONENARGS) $< > $@
-
-GENSRC_LOCALEDATAMETAINFO := $(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/EnLocaleDataMetaInfo.java \
- $(JDK_OUTPUTDIR)/gensrc/jdk.localedata/sun/util/resources/provider/NonEnLocaleDataMetaInfo.java
-
-################################################################################
-
-GENSRC_CRBC_DST := $(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/CoreResourceBundleControl.java
-GENSRC_CRBC_CMD := $(JDK_TOPDIR)/make/scripts/localelist.sh
-
-JRE_NONEXIST_LOCALES := en en_US de_DE es_ES fr_FR it_IT ja_JP ko_KR sv_SE zh
-
-$(GENSRC_CRBC_DST): $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/CoreResourceBundleControl-XLocales.java.template \
- $(GENSRC_CRBC_CMD)
- $(MKDIR) -p $(@D)
- NAWK="$(NAWK)" SED="$(SED)" $(SH) $(GENSRC_CRBC_CMD) "$(JRE_NONEXIST_LOCALES)" $< $@
-
-GENSRC_LOCALEDATAMETAINFO += $(GENSRC_CRBC_DST)
-GENSRC_JAVA_BASE += $(GENSRC_LOCALEDATAMETAINFO)
-
-################################################################################
--- a/jdk/make/lib/Awt2dLibraries.gmk Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/make/lib/Awt2dLibraries.gmk Wed Jul 05 20:01:44 2017 +0200
@@ -217,10 +217,8 @@
-I$(JDK_OUTPUTDIR)/gensrc_headers/java.base \
#
LIBAWT_EXFILES += \
- sun/java2d/d3d/D3DPipeline.cpp \
sun/java2d/d3d/D3DShaderGen.c \
sun/awt/image/cvutils/img_colors.c \
- sun/windows/WBufferStrategy.cpp \
#
LIBAWT_LANG := C++
--- a/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java Wed Jul 05 20:01:44 2017 +0200
@@ -143,8 +143,9 @@
@Override
public void generateMetaInfo(Map<String, SortedSet<String>> metaInfo) throws IOException {
- String dirName = CLDRConverter.DESTINATION_DIR + File.separator + "sun" + File.separator + "util" + File.separator
- + "cldr" + File.separator;
+ String dirName = CLDRConverter.DESTINATION_DIR + File.separator + "sun" + File.separator + "util" +
+ File.separator + "resources" + File.separator + "cldr" + File.separator +
+ "provider" + File.separator ;
File dir = new File(dirName);
if (!dir.exists()) {
dir.mkdirs();
@@ -158,7 +159,7 @@
try (PrintWriter out = new PrintWriter(file, "us-ascii")) {
out.println(CopyrightHeaders.getOpenJDKCopyright());
- out.println("package sun.util.cldr;\n\n"
+ out.println("package sun.util.resources.cldr.provider;\n\n"
+ "import java.util.ListResourceBundle;\n"
+ "import sun.util.locale.provider.LocaleProviderAdapter;\n"
+ "import sun.util.locale.provider.LocaleDataMetaInfo;\n");
--- a/jdk/make/src/classes/build/tools/module/GenJdepsModulesXml.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/make/src/classes/build/tools/module/GenJdepsModulesXml.java Wed Jul 05 20:01:44 2017 +0200
@@ -25,29 +25,17 @@
package build.tools.module;
-import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
+import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.Map;
-import java.util.Objects;
import java.util.Set;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import javax.xml.namespace.QName;
-import javax.xml.stream.*;
-import javax.xml.stream.events.Attribute;
-import javax.xml.stream.events.XMLEvent;
+import java.util.stream.Collectors;
/**
* GenJdepsModulesXml augments the input modules.xml file(s)
@@ -97,14 +85,14 @@
Set<Module> modules = new HashSet<>();
for (; i < args.length; i++) {
Path p = Paths.get(args[i]);
- try (InputStream in = new BufferedInputStream(Files.newInputStream(p))) {
- Set<Module> mods = gentool.load(in);
- modules.addAll(mods);
- }
+ modules.addAll(ModulesXmlReader.readModules(p)
+ .stream()
+ .map(gentool::buildIncludes)
+ .collect(Collectors.toSet()));
}
Files.createDirectories(outfile.getParent());
- gentool.writeXML(modules, outfile);
+ ModulesXmlWriter.writeModules(modules, outfile);
}
final Path modulepath;
@@ -112,228 +100,21 @@
this.modulepath = modulepath;
}
- private static final String MODULES = "modules";
- private static final String MODULE = "module";
- private static final String NAME = "name";
- private static final String DEPEND = "depend";
- private static final String EXPORT = "export";
- private static final String TO = "to";
- private static final String INCLUDE = "include";
- private static final QName REEXPORTS = new QName("re-exports");
- private Set<Module> load(InputStream in) throws XMLStreamException, IOException {
- Set<Module> modules = new HashSet<>();
- XMLInputFactory factory = XMLInputFactory.newInstance();
- XMLEventReader stream = factory.createXMLEventReader(in);
- Module.Builder mb = null;
- String modulename = null;
- String pkg = null;
- Set<String> permits = new HashSet<>();
- while (stream.hasNext()) {
- XMLEvent event = stream.nextEvent();
- if (event.isStartElement()) {
- String startTag = event.asStartElement().getName().getLocalPart();
- switch (startTag) {
- case MODULES:
- break;
- case MODULE:
- if (mb != null) {
- throw new RuntimeException("end tag for module is missing");
- }
- modulename = getNextTag(stream, NAME);
- mb = new Module.Builder();
- mb.name(modulename);
- break;
- case NAME:
- throw new RuntimeException(event.toString());
- case DEPEND:
- boolean reexports = false;
- Attribute attr = event.asStartElement().getAttributeByName(REEXPORTS);
- if (attr != null) {
- String value = attr.getValue();
- if (value.equals("true") || value.equals("false")) {
- reexports = Boolean.parseBoolean(value);
- } else {
- throw new RuntimeException("unexpected attribute " + attr.toString());
- }
- }
- mb.require(getData(stream), reexports);
- break;
- case INCLUDE:
- throw new RuntimeException("unexpected " + event);
- case EXPORT:
- pkg = getNextTag(stream, NAME);
- break;
- case TO:
- permits.add(getData(stream));
- break;
- default:
- }
- } else if (event.isEndElement()) {
- String endTag = event.asEndElement().getName().getLocalPart();
- switch (endTag) {
- case MODULE:
- buildIncludes(mb, modulename);
- modules.add(mb.build());
- mb = null;
- break;
- case EXPORT:
- if (pkg == null) {
- throw new RuntimeException("export-to is malformed");
- }
- mb.exportTo(pkg, permits);
- pkg = null;
- permits.clear();
- break;
- default:
- }
- } else if (event.isCharacters()) {
- String s = event.asCharacters().getData();
- if (!s.trim().isEmpty()) {
- throw new RuntimeException("export-to is malformed");
- }
- }
- }
- return modules;
- }
-
- private String getData(XMLEventReader reader) throws XMLStreamException {
- XMLEvent e = reader.nextEvent();
- if (e.isCharacters()) {
- return e.asCharacters().getData();
- }
- throw new RuntimeException(e.toString());
- }
-
- private String getNextTag(XMLEventReader reader, String tag) throws XMLStreamException {
- XMLEvent e = reader.nextTag();
- if (e.isStartElement()) {
- String t = e.asStartElement().getName().getLocalPart();
- if (!tag.equals(t)) {
- throw new RuntimeException(e + " expected: " + tag);
- }
- return getData(reader);
- }
- throw new RuntimeException("export-to name is missing:" + e);
- }
- private void writeXML(Set<Module> modules, Path path)
- throws IOException, XMLStreamException
- {
- XMLOutputFactory xof = XMLOutputFactory.newInstance();
- try (OutputStream out = Files.newOutputStream(path)) {
- int depth = 0;
- XMLStreamWriter xtw = xof.createXMLStreamWriter(out, "UTF-8");
- xtw.writeStartDocument("utf-8","1.0");
- writeStartElement(xtw, MODULES, depth);
- modules.stream()
- .sorted(Comparator.comparing(Module::name))
- .forEach(m -> writeModuleElement(xtw, m, depth+1));
- writeEndElement(xtw, depth);
- xtw.writeCharacters("\n");
- xtw.writeEndDocument();
- xtw.flush();
- xtw.close();
- }
- }
-
- private void writeElement(XMLStreamWriter xtw, String element, String value, int depth) {
- try {
- writeStartElement(xtw, element, depth);
- xtw.writeCharacters(value);
- xtw.writeEndElement();
- } catch (XMLStreamException e) {
- throw new RuntimeException(e);
- }
- }
-
- private void writeDependElement(XMLStreamWriter xtw, Module.Dependence d, int depth) {
- try {
- writeStartElement(xtw, DEPEND, depth);
- if (d.reexport) {
- xtw.writeAttribute("re-exports", "true");
- }
- xtw.writeCharacters(d.name);
- xtw.writeEndElement();
- } catch (XMLStreamException e) {
- throw new RuntimeException(e);
- }
- }
-
- private void writeExportElement(XMLStreamWriter xtw, String pkg, int depth) {
- writeExportElement(xtw, pkg, Collections.emptySet(), depth);
- }
-
- private void writeExportElement(XMLStreamWriter xtw, String pkg,
- Set<String> permits, int depth) {
- try {
- writeStartElement(xtw, EXPORT, depth);
- writeElement(xtw, NAME, pkg, depth+1);
- if (!permits.isEmpty()) {
- permits.stream().sorted()
- .forEach(m -> writeElement(xtw, TO, m, depth + 1));
- }
- writeEndElement(xtw, depth);
- } catch (XMLStreamException e) {
- throw new RuntimeException(e);
- }
- }
- private void writeModuleElement(XMLStreamWriter xtw, Module m, int depth) {
- try {
- writeStartElement(xtw, MODULE, depth);
- writeElement(xtw, NAME, m.name(), depth+1);
- m.requires().stream().sorted(Comparator.comparing(d -> d.name))
- .forEach(d -> writeDependElement(xtw, d, depth+1));
- m.exports().keySet().stream()
- .filter(pn -> m.exports().get(pn).isEmpty())
- .sorted()
- .forEach(pn -> writeExportElement(xtw, pn, depth+1));
- m.exports().entrySet().stream()
- .filter(e -> !e.getValue().isEmpty())
- .sorted(Map.Entry.comparingByKey())
- .forEach(e -> writeExportElement(xtw, e.getKey(), e.getValue(), depth+1));
- m.packages().stream().sorted()
- .forEach(p -> writeElement(xtw, INCLUDE, p, depth+1));
- writeEndElement(xtw, depth);
- } catch (XMLStreamException e) {
- throw new RuntimeException(e);
-
- }
- }
-
- /** Two spaces; the default indentation. */
- public static final String DEFAULT_INDENT = " ";
-
- /** stack[depth] indicates what's been written into the current scope. */
- private static String[] stack = new String[] { "\n",
- "\n" + DEFAULT_INDENT,
- "\n" + DEFAULT_INDENT + DEFAULT_INDENT,
- "\n" + DEFAULT_INDENT + DEFAULT_INDENT + DEFAULT_INDENT};
-
- private void writeStartElement(XMLStreamWriter xtw, String name, int depth)
- throws XMLStreamException
- {
- xtw.writeCharacters(stack[depth]);
- xtw.writeStartElement(name);
- }
-
- private void writeEndElement(XMLStreamWriter xtw, int depth) throws XMLStreamException {
- xtw.writeCharacters(stack[depth]);
- xtw.writeEndElement();
- }
-
- private String packageName(Path p) {
+ private static String packageName(Path p) {
return packageName(p.toString().replace(File.separatorChar, '/'));
}
- private String packageName(String name) {
+ private static String packageName(String name) {
int i = name.lastIndexOf('/');
return (i > 0) ? name.substring(0, i).replace('/', '.') : "";
}
- private boolean includes(String name) {
- return name.endsWith(".class") && !name.equals("module-info.class");
+ private static boolean includes(String name) {
+ return name.endsWith(".class");
}
- public void buildIncludes(Module.Builder mb, String modulename) throws IOException {
- Path mclasses = modulepath.resolve(modulename);
+ public Module buildIncludes(Module module) {
+ Module.Builder mb = new Module.Builder(module);
+ Path mclasses = modulepath.resolve(module.name());
try {
Files.find(mclasses, Integer.MAX_VALUE, (Path p, BasicFileAttributes attr)
-> includes(p.getFileName().toString()))
@@ -341,145 +122,9 @@
.forEach(mb::include);
} catch (NoSuchFileException e) {
// aggregate module may not have class
- }
- }
-
- static class Module {
- static class Dependence {
- final String name;
- final boolean reexport;
- Dependence(String name) {
- this(name, false);
- }
- Dependence(String name, boolean reexport) {
- this.name = name;
- this.reexport = reexport;
- }
-
- @Override
- public int hashCode() {
- int hash = 5;
- hash = 11 * hash + Objects.hashCode(this.name);
- hash = 11 * hash + (this.reexport ? 1 : 0);
- return hash;
- }
-
- public boolean equals(Object o) {
- Dependence d = (Dependence)o;
- return this.name.equals(d.name) && this.reexport == d.reexport;
- }
- }
- private final String moduleName;
- private final Set<Dependence> requires;
- private final Map<String, Set<String>> exports;
- private final Set<String> packages;
-
- private Module(String name,
- Set<Dependence> requires,
- Map<String, Set<String>> exports,
- Set<String> packages) {
- this.moduleName = name;
- this.requires = Collections.unmodifiableSet(requires);
- this.exports = Collections.unmodifiableMap(exports);
- this.packages = Collections.unmodifiableSet(packages);
- }
-
- public String name() {
- return moduleName;
- }
-
- public Set<Dependence> requires() {
- return requires;
- }
-
- public Map<String, Set<String>> exports() {
- return exports;
- }
-
- public Set<String> packages() {
- return packages;
- }
-
- @Override
- public boolean equals(Object ob) {
- if (!(ob instanceof Module)) {
- return false;
- }
- Module that = (Module) ob;
- return (moduleName.equals(that.moduleName)
- && requires.equals(that.requires)
- && exports.equals(that.exports)
- && packages.equals(that.packages));
+ } catch (IOException ioe) {
+ throw new UncheckedIOException(ioe);
}
-
- @Override
- public int hashCode() {
- int hc = moduleName.hashCode();
- hc = hc * 43 + requires.hashCode();
- hc = hc * 43 + exports.hashCode();
- hc = hc * 43 + packages.hashCode();
- return hc;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("module ").append(moduleName).append(" {").append("\n");
- requires.stream().sorted().forEach(d ->
- sb.append(String.format(" requires %s%s%n", d.reexport ? "public " : "", d.name)));
- exports.entrySet().stream().filter(e -> e.getValue().isEmpty())
- .sorted(Map.Entry.comparingByKey())
- .forEach(e -> sb.append(String.format(" exports %s%n", e.getKey())));
- exports.entrySet().stream().filter(e -> !e.getValue().isEmpty())
- .sorted(Map.Entry.comparingByKey())
- .forEach(e -> sb.append(String.format(" exports %s to %s%n", e.getKey(), e.getValue())));
- packages.stream().sorted().forEach(pn -> sb.append(String.format(" includes %s%n", pn)));
- sb.append("}");
- return sb.toString();
- }
-
- static class Builder {
- private String name;
- private final Set<Dependence> requires = new HashSet<>();
- private final Map<String, Set<String>> exports = new HashMap<>();
- private final Set<String> packages = new HashSet<>();
-
- public Builder() {
- }
-
- public Builder name(String n) {
- name = n;
- return this;
- }
-
- public Builder require(String d, boolean reexport) {
- requires.add(new Dependence(d, reexport));
- return this;
- }
-
- public Builder include(String p) {
- packages.add(p);
- return this;
- }
-
- public Builder export(String p) {
- return exportTo(p, Collections.emptySet());
- }
-
- public Builder exportTo(String p, Set<String> ms) {
- Objects.requireNonNull(p);
- Objects.requireNonNull(ms);
- if (exports.containsKey(p)) {
- throw new RuntimeException(name + " already exports " + p);
- }
- exports.put(p, new HashSet<>(ms));
- return this;
- }
-
- public Module build() {
- Module m = new Module(name, requires, exports, packages);
- return m;
- }
- }
+ return mb.build();
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/src/classes/build/tools/module/GenModulesList.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2014, 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 build.tools.module;
+
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * $ java build.tools.module.GenModulesList \
+ * -o modules.list \
+ * top/modules.xml ...
+ */
+public final class GenModulesList {
+ private final static String USAGE =
+ "Usage: GenModulesList -o <output file> path-to-modules-xml";
+
+ private Set<Module> modules = new HashSet<>();
+ private HashMap<String,Module> nameToModule = new HashMap<>();
+
+ public static void main(String[] args) throws Exception {
+ GenModulesList gen = new GenModulesList();
+ gen.run(args);
+ }
+
+ void run(String[] args) throws Exception {
+ Path outfile = null;
+ int i = 0;
+ while (i < args.length) {
+ String arg = args[i];
+ if (arg.equals("-o")) {
+ outfile = Paths.get(args[i+1]);
+ i = i+2;
+ } else {
+ break;
+ }
+ }
+ if (outfile == null || i >= args.length) {
+ System.err.println(USAGE);
+ System.exit(-1);
+ }
+
+ for (; i < args.length; i++) {
+ Path p = Paths.get(args[i]);
+ modules.addAll(ModulesXmlReader.readModules(p));
+ }
+
+ modules.stream()
+ .forEach(m -> nameToModule.put(m.name(), m));
+
+ Path parent = outfile.getParent();
+ if (parent != null)
+ Files.createDirectories(parent);
+
+ Iterable<Module> sortedModules = (new TopoSorter(modules)).result();
+ try (PrintWriter writer = new PrintWriter(outfile.toFile())) {
+ for (Module m : sortedModules) {
+ if (isNotAggregator(m)) {
+ String deps = getModuleDependences(m).stream()
+ .filter(GenModulesList::isNotAggregator)
+ .map(Module::name)
+ .collect(Collectors.joining(" "));
+ writer.format("%s: %s%n", m.name(), deps);
+ }
+ }
+ }
+ }
+
+ private Module nameToModule(String name) {
+ return nameToModule.get(name);
+ }
+
+ private Set<Module> getModuleDependences(Module m) {
+ return m.requires().stream()
+ .map(d -> d.name())
+ .map(this::nameToModule)
+ .collect(Collectors.toSet());
+ }
+
+ static boolean isNotAggregator(Module m) {
+ return isNotAggregator(m.name());
+ }
+
+ static boolean isNotAggregator(String name) {
+ return AGGREGATORS.contains(name) ? false : true;
+ }
+
+ static final List<String> AGGREGATORS = Arrays.asList(new String[] {
+ "java.se", "java.compact1", "java.compact2",
+ "java.compact3", "jdk.compact3"});
+
+ class TopoSorter {
+ final Deque<Module> result = new LinkedList<>();
+ final Deque<Module> nodes = new LinkedList<>();
+
+ TopoSorter(Collection<Module> nodes) {
+ nodes.stream()
+ .forEach(m -> this.nodes.add(m));
+
+ sort();
+ }
+
+ public Iterable<Module> result() {
+ return result;
+ }
+
+ private void sort() {
+ Deque<Module> visited = new LinkedList<>();
+ Deque<Module> done = new LinkedList<>();
+ Module node;
+ while ((node = nodes.poll()) != null) {
+ if (!visited.contains(node)) {
+ visit(node, visited, done);
+ }
+ }
+ }
+
+ private void visit(Module m, Deque<Module> visited, Deque<Module> done) {
+ if (visited.contains(m)) {
+ if (!done.contains(m)) {
+ throw new IllegalArgumentException("Cyclic detected: " +
+ m + " " + getModuleDependences(m));
+ }
+ return;
+ }
+ visited.add(m);
+ getModuleDependences(m).stream()
+ .forEach(x -> visit(x, visited, done));
+ done.add(m);
+ result.addLast(m);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/src/classes/build/tools/module/Module.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2014, 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 build.tools.module;
+
+import java.util.*;
+
+public class Module {
+ static class Dependence {
+ final String name;
+ final boolean reexport;
+ Dependence(String name) {
+ this(name, false);
+ }
+ Dependence(String name, boolean reexport) {
+ this.name = name;
+ this.reexport = reexport;
+ }
+
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 5;
+ hash = 11 * hash + Objects.hashCode(this.name);
+ hash = 11 * hash + (this.reexport ? 1 : 0);
+ return hash;
+ }
+
+ public boolean equals(Object o) {
+ Dependence d = (Dependence)o;
+ return this.name.equals(d.name) && this.reexport == d.reexport;
+ }
+ }
+ private final String moduleName;
+ private final Set<Dependence> requires;
+ private final Map<String, Set<String>> exports;
+ private final Set<String> packages;
+
+ private Module(String name,
+ Set<Dependence> requires,
+ Map<String, Set<String>> exports,
+ Set<String> packages) {
+ this.moduleName = name;
+ this.requires = Collections.unmodifiableSet(requires);
+ this.exports = Collections.unmodifiableMap(exports);
+ this.packages = Collections.unmodifiableSet(packages);
+ }
+
+ public String name() {
+ return moduleName;
+ }
+
+ public Set<Dependence> requires() {
+ return requires;
+ }
+
+ public Map<String, Set<String>> exports() {
+ return exports;
+ }
+
+ public Set<String> packages() {
+ return packages;
+ }
+
+ @Override
+ public boolean equals(Object ob) {
+ if (!(ob instanceof Module)) {
+ return false;
+ }
+ Module that = (Module) ob;
+ return (moduleName.equals(that.moduleName)
+ && requires.equals(that.requires)
+ && exports.equals(that.exports)
+ && packages.equals(that.packages));
+ }
+
+ @Override
+ public int hashCode() {
+ int hc = moduleName.hashCode();
+ hc = hc * 43 + requires.hashCode();
+ hc = hc * 43 + exports.hashCode();
+ hc = hc * 43 + packages.hashCode();
+ return hc;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("module ").append(moduleName).append(" {").append("\n");
+ requires.stream().sorted().forEach(d ->
+ sb.append(String.format(" requires %s%s%n", d.reexport ? "public " : "", d.name)));
+ exports.entrySet().stream().filter(e -> e.getValue().isEmpty())
+ .sorted(Map.Entry.comparingByKey())
+ .forEach(e -> sb.append(String.format(" exports %s%n", e.getKey())));
+ exports.entrySet().stream().filter(e -> !e.getValue().isEmpty())
+ .sorted(Map.Entry.comparingByKey())
+ .forEach(e -> sb.append(String.format(" exports %s to %s%n", e.getKey(), e.getValue())));
+ packages.stream().sorted().forEach(pn -> sb.append(String.format(" includes %s%n", pn)));
+ sb.append("}");
+ return sb.toString();
+ }
+
+ static class Builder {
+ private String name;
+ private final Set<Dependence> requires = new HashSet<>();
+ private final Map<String, Set<String>> exports = new HashMap<>();
+ private final Set<String> packages = new HashSet<>();
+
+ public Builder() {
+ }
+
+ public Builder(Module module) {
+ name = module.name();
+ requires.addAll(module.requires());
+ exports.putAll(module.exports());
+ packages.addAll(module.packages());
+ }
+
+ public Builder name(String n) {
+ name = n;
+ return this;
+ }
+
+ public Builder require(String d, boolean reexport) {
+ requires.add(new Dependence(d, reexport));
+ return this;
+ }
+
+ public Builder include(String p) {
+ packages.add(p);
+ return this;
+ }
+
+ public Builder export(String p) {
+ return exportTo(p, Collections.emptySet());
+ }
+
+ public Builder exportTo(String p, Set<String> ms) {
+ Objects.requireNonNull(p);
+ Objects.requireNonNull(ms);
+ if (exports.containsKey(p)) {
+ throw new RuntimeException(name + " already exports " + p);
+ }
+ exports.put(p, new HashSet<>(ms));
+ return this;
+ }
+
+ public Module build() {
+ Module m = new Module(name, requires, exports, packages);
+ return m;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/src/classes/build/tools/module/ModulesXmlReader.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2014, 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 build.tools.module;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.XMLEvent;
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashSet;
+import java.util.Set;
+
+public class ModulesXmlReader {
+
+ private ModulesXmlReader() {}
+
+ public static Set<Module> readModules(Path modulesXml)
+ throws XMLStreamException, IOException
+ {
+ Set<Module> modules = new HashSet<>();
+ try (InputStream in = new BufferedInputStream(Files.newInputStream(modulesXml))) {
+ Set<Module> mods = ModulesXmlReader.load(in);
+ modules.addAll(mods);
+ }
+ return modules;
+ }
+
+ private static final String MODULES = "modules";
+ private static final String MODULE = "module";
+ private static final String NAME = "name";
+ private static final String DEPEND = "depend";
+ private static final String EXPORT = "export";
+ private static final String TO = "to";
+ private static final String INCLUDE = "include";
+ private static final QName REEXPORTS = new QName("re-exports");
+ private static Set<Module> load(InputStream in)
+ throws XMLStreamException, IOException
+ {
+ Set<Module> modules = new HashSet<>();
+ XMLInputFactory factory = XMLInputFactory.newInstance();
+ XMLEventReader stream = factory.createXMLEventReader(in);
+ Module.Builder mb = null;
+ String modulename = null;
+ String pkg = null;
+ Set<String> permits = new HashSet<>();
+ while (stream.hasNext()) {
+ XMLEvent event = stream.nextEvent();
+ if (event.isStartElement()) {
+ String startTag = event.asStartElement().getName().getLocalPart();
+ switch (startTag) {
+ case MODULES:
+ break;
+ case MODULE:
+ if (mb != null) {
+ throw new RuntimeException("end tag for module is missing");
+ }
+ modulename = getNextTag(stream, NAME);
+ mb = new Module.Builder();
+ mb.name(modulename);
+ break;
+ case NAME:
+ throw new RuntimeException(event.toString());
+ case DEPEND:
+ boolean reexports = false;
+ Attribute attr = event.asStartElement().getAttributeByName(REEXPORTS);
+ if (attr != null) {
+ String value = attr.getValue();
+ if (value.equals("true") || value.equals("false")) {
+ reexports = Boolean.parseBoolean(value);
+ } else {
+ throw new RuntimeException("unexpected attribute " + attr.toString());
+ }
+ }
+ mb.require(getData(stream), reexports);
+ break;
+ case INCLUDE:
+ throw new RuntimeException("unexpected " + event);
+ case EXPORT:
+ pkg = getNextTag(stream, NAME);
+ break;
+ case TO:
+ permits.add(getData(stream));
+ break;
+ default:
+ }
+ } else if (event.isEndElement()) {
+ String endTag = event.asEndElement().getName().getLocalPart();
+ switch (endTag) {
+ case MODULE:
+ modules.add(mb.build());
+ mb = null;
+ break;
+ case EXPORT:
+ if (pkg == null) {
+ throw new RuntimeException("export-to is malformed");
+ }
+ mb.exportTo(pkg, permits);
+ pkg = null;
+ permits.clear();
+ break;
+ default:
+ }
+ } else if (event.isCharacters()) {
+ String s = event.asCharacters().getData();
+ if (!s.trim().isEmpty()) {
+ throw new RuntimeException("export-to is malformed");
+ }
+ }
+ }
+ return modules;
+ }
+
+ private static String getData(XMLEventReader reader)
+ throws XMLStreamException
+ {
+ XMLEvent e = reader.nextEvent();
+ if (e.isCharacters())
+ return e.asCharacters().getData();
+
+ throw new RuntimeException(e.toString());
+ }
+
+ private static String getNextTag(XMLEventReader reader, String tag)
+ throws XMLStreamException
+ {
+ XMLEvent e = reader.nextTag();
+ if (e.isStartElement()) {
+ String t = e.asStartElement().getName().getLocalPart();
+ if (!tag.equals(t)) {
+ throw new RuntimeException(e + " expected: " + tag);
+ }
+ return getData(reader);
+ }
+ throw new RuntimeException("export-to name is missing:" + e);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/src/classes/build/tools/module/ModulesXmlWriter.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2014, 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 build.tools.module;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.Set;
+
+public final class ModulesXmlWriter {
+
+ private ModulesXmlWriter() {}
+
+ public static void writeModules(Set<Module> modules, Path path)
+ throws IOException, XMLStreamException
+ {
+ writeXML(modules, path);
+ }
+
+ private static final String MODULES = "modules";
+ private static final String MODULE = "module";
+ private static final String NAME = "name";
+ private static final String DEPEND = "depend";
+ private static final String EXPORT = "export";
+ private static final String TO = "to";
+ private static final String INCLUDE = "include";
+ private static final QName REEXPORTS = new QName("re-exports");
+
+ private static void writeXML(Set<Module> modules, Path path)
+ throws IOException, XMLStreamException
+ {
+ XMLOutputFactory xof = XMLOutputFactory.newInstance();
+ try (OutputStream out = Files.newOutputStream(path)) {
+ int depth = 0;
+ XMLStreamWriter xtw = xof.createXMLStreamWriter(out, "UTF-8");
+ xtw.writeStartDocument("utf-8","1.0");
+ writeStartElement(xtw, MODULES, depth);
+ modules.stream()
+ .sorted(Comparator.comparing(Module::name))
+ .forEach(m -> writeModuleElement(xtw, m, depth+1));
+ writeEndElement(xtw, depth);
+ xtw.writeCharacters("\n");
+ xtw.writeEndDocument();
+ xtw.flush();
+ xtw.close();
+ }
+ }
+
+ private static void writeElement(XMLStreamWriter xtw,
+ String element,
+ String value,
+ int depth) {
+ try {
+ writeStartElement(xtw, element, depth);
+ xtw.writeCharacters(value);
+ xtw.writeEndElement();
+ } catch (XMLStreamException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static void writeDependElement(XMLStreamWriter xtw,
+ Module.Dependence d,
+ int depth) {
+ try {
+ writeStartElement(xtw, DEPEND, depth);
+ if (d.reexport) {
+ xtw.writeAttribute("re-exports", "true");
+ }
+ xtw.writeCharacters(d.name);
+ xtw.writeEndElement();
+ } catch (XMLStreamException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static void writeExportElement(XMLStreamWriter xtw,
+ String pkg,
+ int depth) {
+ writeExportElement(xtw, pkg, Collections.emptySet(), depth);
+ }
+
+ private static void writeExportElement(XMLStreamWriter xtw,
+ String pkg,
+ Set<String> permits,
+ int depth) {
+ try {
+ writeStartElement(xtw, EXPORT, depth);
+ writeElement(xtw, NAME, pkg, depth+1);
+ if (!permits.isEmpty()) {
+ permits.stream().sorted()
+ .forEach(m -> writeElement(xtw, TO, m, depth + 1));
+ }
+ writeEndElement(xtw, depth);
+ } catch (XMLStreamException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ private static void writeModuleElement(XMLStreamWriter xtw,
+ Module m,
+ int depth) {
+ try {
+ writeStartElement(xtw, MODULE, depth);
+ writeElement(xtw, NAME, m.name(), depth+1);
+ m.requires().stream().sorted(Comparator.comparing(d -> d.name))
+ .forEach(d -> writeDependElement(xtw, d, depth+1));
+ m.exports().keySet().stream()
+ .filter(pn -> m.exports().get(pn).isEmpty())
+ .sorted()
+ .forEach(pn -> writeExportElement(xtw, pn, depth+1));
+ m.exports().entrySet().stream()
+ .filter(e -> !e.getValue().isEmpty())
+ .sorted(Map.Entry.comparingByKey())
+ .forEach(e -> writeExportElement(xtw, e.getKey(), e.getValue(), depth+1));
+ m.packages().stream().sorted()
+ .forEach(p -> writeElement(xtw, INCLUDE, p, depth+1));
+ writeEndElement(xtw, depth);
+ } catch (XMLStreamException e) {
+ throw new RuntimeException(e);
+
+ }
+ }
+
+ /** Two spaces; the default indentation. */
+ public static final String DEFAULT_INDENT = " ";
+
+ /** stack[depth] indicates what's been written into the current scope. */
+ private static String[] stack = new String[] { "\n",
+ "\n" + DEFAULT_INDENT,
+ "\n" + DEFAULT_INDENT + DEFAULT_INDENT,
+ "\n" + DEFAULT_INDENT + DEFAULT_INDENT + DEFAULT_INDENT};
+
+ private static void writeStartElement(XMLStreamWriter xtw,
+ String name,
+ int depth)
+ throws XMLStreamException
+ {
+ xtw.writeCharacters(stack[depth]);
+ xtw.writeStartElement(name);
+ }
+
+ private static void writeEndElement(XMLStreamWriter xtw, int depth)
+ throws XMLStreamException
+ {
+ xtw.writeCharacters(stack[depth]);
+ xtw.writeEndElement();
+ }
+}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Wed Jul 05 20:01:44 2017 +0200
@@ -62,7 +62,7 @@
private static final String CLL_SIG = "(L" + CLS + ";L" + OBJ + ";)L" + OBJ + ";";
/** Name of its super class*/
- private static final String superName = LF;
+ private static final String superName = OBJ;
/** Name of new class */
private final String className;
@@ -97,7 +97,7 @@
if (DUMP_CLASS_FILES) {
className = makeDumpableClassName(className);
}
- this.className = superName + "$" + className;
+ this.className = LF + "$" + className;
this.sourceFile = "LambdaForm$" + className;
this.lambdaForm = lambdaForm;
this.invokerName = invokerName;
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Jul 05 20:01:44 2017 +0200
@@ -188,7 +188,6 @@
static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType,
boolean strict, boolean monobox) {
MethodType dstType = target.type();
- assert(dstType.parameterCount() == target.type().parameterCount());
if (srcType == dstType)
return target;
if (USE_LAMBDA_FORM_EDITOR) {
@@ -265,6 +264,7 @@
static MethodHandle makePairwiseConvertIndirect(MethodHandle target, MethodType srcType,
boolean strict, boolean monobox) {
+ assert(target.type().parameterCount() == srcType.parameterCount());
// Calculate extra arguments (temporaries) required in the names array.
Object[] convSpecs = computeValueConversions(srcType, target.type(), strict, monobox);
final int INARG_COUNT = srcType.parameterCount();
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Wed Jul 05 20:01:44 2017 +0200
@@ -2023,8 +2023,9 @@
*/
public static
MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) {
+ explicitCastArgumentsChecks(target, newType);
+ // use the asTypeCache when possible:
MethodType oldType = target.type();
- // use the asTypeCache when possible:
if (oldType == newType) return target;
if (oldType.explicitCastEquivalentToAsType(newType)) {
return target.asType(newType);
@@ -2032,6 +2033,12 @@
return MethodHandleImpl.makePairwiseConvert(target, newType, false);
}
+ private static void explicitCastArgumentsChecks(MethodHandle target, MethodType newType) {
+ if (target.type().parameterCount() != newType.parameterCount()) {
+ throw new WrongMethodTypeException("cannot explicitly cast " + target + " to " + newType);
+ }
+ }
+
/**
* Produces a method handle which adapts the calling sequence of the
* given method handle to a new type, by reordering the arguments.
@@ -2164,7 +2171,7 @@
// dropIdx is missing from reorder; add it in at the end
int oldArity = reorder.length;
target = dropArguments(target, oldArity, newType.parameterType(dropIdx));
- reorder = Arrays.copyOf(reorder, oldArity+1);
+ reorder = Arrays.copyOf(reorder, oldArity + 1);
reorder[oldArity] = dropIdx;
}
assert(target == originalTarget || permuteArgumentChecks(reorder, newType, target.type()));
@@ -2182,9 +2189,9 @@
long mask = 0;
for (int arg : reorder) {
assert(arg < newArity);
- mask |= (1 << arg);
+ mask |= (1L << arg);
}
- if (mask == (1 << newArity) - 1) {
+ if (mask == (1L << newArity) - 1) {
assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity);
return -1;
}
@@ -2193,16 +2200,18 @@
int zeroPos = Long.numberOfTrailingZeros(zeroBit);
assert(zeroPos < newArity);
return zeroPos;
+ } else {
+ BitSet mask = new BitSet(newArity);
+ for (int arg : reorder) {
+ assert (arg < newArity);
+ mask.set(arg);
+ }
+ int zeroPos = mask.nextClearBit(0);
+ assert(zeroPos <= newArity);
+ if (zeroPos == newArity)
+ return -1;
+ return zeroPos;
}
- BitSet mask = new BitSet(newArity);
- for (int arg : reorder) {
- assert(arg < newArity);
- mask.set(arg);
- }
- int zeroPos = mask.nextClearBit(0);
- if (zeroPos == newArity)
- return -1;
- return zeroPos;
}
/**
@@ -2218,32 +2227,42 @@
long mask = 0;
for (int i = 0; i < reorder.length; i++) {
int arg = reorder[i];
- if (arg >= newArity) return reorder.length;
- int bit = 1 << arg;
- if ((mask & bit) != 0)
+ if (arg >= newArity) {
+ return reorder.length;
+ }
+ long bit = 1L << arg;
+ if ((mask & bit) != 0) {
return i; // >0 indicates a dup
+ }
mask |= bit;
}
- if (mask == (1 << newArity) - 1) {
+ if (mask == (1L << newArity) - 1) {
assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity);
return 0;
}
// find first zero
long zeroBit = Long.lowestOneBit(~mask);
int zeroPos = Long.numberOfTrailingZeros(zeroBit);
- assert(zeroPos < newArity);
+ assert(zeroPos <= newArity);
+ if (zeroPos == newArity) {
+ return 0;
+ }
return ~zeroPos;
} else {
// same algorithm, different bit set
BitSet mask = new BitSet(newArity);
for (int i = 0; i < reorder.length; i++) {
int arg = reorder[i];
- if (arg >= newArity) return reorder.length;
- if (mask.get(arg))
+ if (arg >= newArity) {
+ return reorder.length;
+ }
+ if (mask.get(arg)) {
return i; // >0 indicates a dup
+ }
mask.set(arg);
}
int zeroPos = mask.nextClearBit(0);
+ assert(zeroPos <= newArity);
if (zeroPos == newArity) {
return 0;
}
@@ -2479,6 +2498,7 @@
MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
MethodType oldType = target.type(); // get NPE
int dropped = dropArgumentChecks(oldType, pos, valueTypes);
+ MethodType newType = oldType.insertParameterTypes(pos, valueTypes);
if (dropped == 0) return target;
BoundMethodHandle result = target.rebind();
LambdaForm lform = result.form;
@@ -2490,7 +2510,6 @@
} else {
lform = lform.addArguments(pos, valueTypes);
}
- MethodType newType = oldType.insertParameterTypes(pos, valueTypes);
result = result.copyWith(newType, lform);
return result;
}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java Wed Jul 05 20:01:44 2017 +0200
@@ -869,9 +869,7 @@
if (dstTypes == srcTypes) {
return true;
}
- if (dstTypes.length != srcTypes.length) {
- return false;
- }
+ assert(dstTypes.length == srcTypes.length);
for (int i = 0; i < dstTypes.length; i++) {
if (!explicitCastEquivalentToAsType(srcTypes[i], dstTypes[i])) {
return false;
--- a/jdk/src/java.base/share/classes/java/math/MutableBigInteger.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/math/MutableBigInteger.java Wed Jul 05 20:01:44 2017 +0200
@@ -1261,19 +1261,20 @@
int sigma = (int) Math.max(0, n32 - b.bitLength()); // step 3: sigma = max{T | (2^T)*B < beta^n}
MutableBigInteger bShifted = new MutableBigInteger(b);
bShifted.safeLeftShift(sigma); // step 4a: shift b so its length is a multiple of n
- safeLeftShift(sigma); // step 4b: shift this by the same amount
+ MutableBigInteger aShifted = new MutableBigInteger (this);
+ aShifted.safeLeftShift(sigma); // step 4b: shift a by the same amount
- // step 5: t is the number of blocks needed to accommodate this plus one additional bit
- int t = (int) ((bitLength()+n32) / n32);
+ // step 5: t is the number of blocks needed to accommodate a plus one additional bit
+ int t = (int) ((aShifted.bitLength()+n32) / n32);
if (t < 2) {
t = 2;
}
- // step 6: conceptually split this into blocks a[t-1], ..., a[0]
- MutableBigInteger a1 = getBlock(t-1, t, n); // the most significant block of this
+ // step 6: conceptually split a into blocks a[t-1], ..., a[0]
+ MutableBigInteger a1 = aShifted.getBlock(t-1, t, n); // the most significant block of a
// step 7: z[t-2] = [a[t-1], a[t-2]]
- MutableBigInteger z = getBlock(t-2, t, n); // the second to most significant block
+ MutableBigInteger z = aShifted.getBlock(t-2, t, n); // the second to most significant block
z.addDisjoint(a1, n); // z[t-2]
// do schoolbook division on blocks, dividing 2-block numbers by 1-block numbers
@@ -1284,7 +1285,7 @@
ri = z.divide2n1n(bShifted, qi);
// step 8b: z = [ri, a[i-1]]
- z = getBlock(i-1, t, n); // a[i-1]
+ z = aShifted.getBlock(i-1, t, n); // a[i-1]
z.addDisjoint(ri, n);
quotient.addShifted(qi, i*n); // update q (part of step 9)
}
@@ -1292,7 +1293,7 @@
ri = z.divide2n1n(bShifted, qi);
quotient.add(qi);
- ri.rightShift(sigma); // step 9: this and b were shifted, so shift back
+ ri.rightShift(sigma); // step 9: a and b were shifted, so shift back
return ri;
}
}
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipInputStream.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipInputStream.java Wed Jul 05 20:01:44 2017 +0200
@@ -336,8 +336,21 @@
return new ZipEntry(name);
}
- /*
+ /**
* Reads end of deflated entry as well as EXT descriptor if present.
+ *
+ * Local headers for DEFLATED entries may optionally be followed by a
+ * data descriptor, and that data descriptor may optionally contain a
+ * leading signature (EXTSIG).
+ *
+ * From the zip spec http://www.pkware.com/documents/casestudies/APPNOTE.TXT
+ *
+ * """Although not originally assigned a signature, the value 0x08074b50
+ * has commonly been adopted as a signature value for the data descriptor
+ * record. Implementers should be aware that ZIP files may be
+ * encountered with or without this signature marking data descriptors
+ * and should account for either case when reading ZIP files to ensure
+ * compatibility."""
*/
private void readEnd(ZipEntry e) throws IOException {
int n = inf.getRemaining();
@@ -356,7 +369,7 @@
e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC);
e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC);
((PushbackInputStream)in).unread(
- tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC);
+ tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC, ZIP64_EXTCRC);
} else {
e.crc = get32(tmpbuf, ZIP64_EXTCRC);
e.csize = get64(tmpbuf, ZIP64_EXTSIZ);
@@ -370,7 +383,7 @@
e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
e.size = get32(tmpbuf, EXTLEN - EXTCRC);
((PushbackInputStream)in).unread(
- tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
+ tmpbuf, EXTHDR - EXTCRC, EXTCRC);
} else {
e.crc = get32(tmpbuf, EXTCRC);
e.csize = get32(tmpbuf, EXTSIZ);
--- a/jdk/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c Wed Jul 05 20:01:44 2017 +0200
@@ -34,6 +34,10 @@
#include <fcntl.h>
#include <sys/uio.h>
#include <unistd.h>
+#if defined(__linux__)
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#endif
#include "nio.h"
#include "nio_util.h"
@@ -177,10 +181,21 @@
JNIEXPORT jlong JNICALL
Java_sun_nio_ch_FileDispatcherImpl_size0(JNIEnv *env, jobject this, jobject fdo)
{
+ jint fd = fdval(env, fdo);
struct stat64 fbuf;
- if (fstat64(fdval(env, fdo), &fbuf) < 0)
+ if (fstat64(fd, &fbuf) < 0)
return handle(env, -1, "Size failed");
+
+#ifdef BLKGETSIZE64
+ if (S_ISBLK(fbuf.st_mode)) {
+ uint64_t size;
+ if (ioctl(fd, BLKGETSIZE64, &size) < 0)
+ return handle(env, -1, "Size failed");
+ return (jlong)size;
+ }
+#endif
+
return fbuf.st_size;
}
--- a/jdk/src/java.base/windows/native/libnet/NetworkInterface.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.base/windows/native/libnet/NetworkInterface.c Wed Jul 05 20:01:44 2017 +0200
@@ -990,9 +990,11 @@
case MIB_IF_TYPE_FDDI:
case IF_TYPE_IEEE80211:
len = ifRowP->dwPhysAddrLen;
- ret = (*env)->NewByteArray(env, len);
- if (!IS_NULL(ret)) {
- (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) ifRowP->bPhysAddr);
+ if (len > 0) {
+ ret = (*env)->NewByteArray(env, len);
+ if (!IS_NULL(ret)) {
+ (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) ifRowP->bPhysAddr);
+ }
}
break;
}
--- a/jdk/src/java.desktop/macosx/classes/sun/awt/datatransfer/flavormap.properties Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-#
-# This properties file is used to initialize the default
-# java.awt.datatransfer.SystemFlavorMap. It contains the Mac OS X platform-specific,
-# default mappings between common Mac OS X selection atoms and platform-independent
-# MIME type strings, which will be converted into
-# java.awt.datatransfer.DataFlavors.
-#
-# The standard format is:
-#
-# <native>=<MIME type>,<MIME type>, ...
-#
-# <native> should be a string identifier that the native platform will
-# recognize as a valid data format. <MIME type> should specify both a MIME
-# primary type and a MIME subtype separated by a '/'. The MIME type may include
-# parameters, where each parameter is a key/value pair separated by '=', and
-# where each parameter to the MIME type is separated by a ';'.
-#
-# Because SystemFlavorMap implements FlavorTable, developers are free to
-# duplicate DataFlavor values and set multiple values for a single native by
-# separating them with ",". If a mapping contains a duplicate key or value,
-# earlier mappings which included this key or value will be preferred.
-#
-# Mappings whose values specify DataFlavors with primary MIME types of
-# "text", and which support the charset parameter, should specify the exact
-# format in which the native platform expects the data. The "charset"
-# parameter specifies the char to byte encoding, the "eoln" parameter
-# specifies the end-of-line marker, and the "terminators" parameter specifies
-# the number of terminating NUL bytes. Note that "eoln" and "terminators"
-# are not standardized MIME type parameters. They are specific to this file
-# format ONLY. They will not appear in any of the DataFlavors returned by the
-# SystemFlavorMap at the Java level.
-#
-# If the "charset" parameter is omitted, or has zero length, the platform
-# default encoding is assumed. If the "eoln" parameter is omitted, or has
-# zero length, "\n" is assumed. If the "terminators" parameter is omitted,
-# or has a value less than zero, zero is assumed.
-#
-# Upon initialization, the data transfer subsystem will record the specified
-# details of the native text format, but the default SystemFlavorMap will
-# present a large set of synthesized DataFlavors which map, in both
-# directions, to the native. After receiving data from the application in one
-# of the synthetic DataFlavors, the data transfer subsystem will transform
-# the data stream into the format specified in this file before passing the
-# transformed stream to the native system.
-#
-# Mappings whose values specify DataFlavors with primary MIME types of
-# "text", but which do not support the charset parameter, will be treated as
-# opaque, 8-bit data. They will not undergo any transformation process, and
-# any "charset", "eoln", or "terminators" parameters specified in this file
-# will be ignored.
-#
-# See java.awt.datatransfer.DataFlavor.selectBestTextFlavor for a list of
-# text flavors which support the charset parameter.
-
-UTF8_STRING=text/plain;charset=UTF-8;eoln="\n";terminators=0
-
-# The COMPOUND_TEXT support for inter-client text transfer is disabled by
-# default. The reason is that many native applications prefer this format over
-# other native text formats, but are unable to decode the textual data in this
-# format properly. This results in java-to-native text transfer failures.
-# To enable the COMPOUND_TEXT support for this JRE installation uncomment
-# the line below.
-
-# COMPOUND_TEXT=text/plain;charset=x-compound-text;eoln="\n";terminators=0
-
-TEXT=text/plain;eoln="\n";terminators=0
-STRING=text/plain;charset=UTF-8;eoln="\n";terminators=0
-FILE_NAME=application/x-java-file-list;class=java.util.List
-text/uri-list=application/x-java-file-list;class=java.util.List
-PNG=image/x-java-image;class=java.awt.Image
-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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/macosx/classes/sun/datatransfer/resources/flavormap.properties Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,76 @@
+#
+# This properties file is used to initialize the default
+# java.awt.datatransfer.SystemFlavorMap. It contains the Mac OS X platform-specific,
+# default mappings between common Mac OS X selection atoms and platform-independent
+# MIME type strings, which will be converted into
+# java.awt.datatransfer.DataFlavors.
+#
+# The standard format is:
+#
+# <native>=<MIME type>,<MIME type>, ...
+#
+# <native> should be a string identifier that the native platform will
+# recognize as a valid data format. <MIME type> should specify both a MIME
+# primary type and a MIME subtype separated by a '/'. The MIME type may include
+# parameters, where each parameter is a key/value pair separated by '=', and
+# where each parameter to the MIME type is separated by a ';'.
+#
+# Because SystemFlavorMap implements FlavorTable, developers are free to
+# duplicate DataFlavor values and set multiple values for a single native by
+# separating them with ",". If a mapping contains a duplicate key or value,
+# earlier mappings which included this key or value will be preferred.
+#
+# Mappings whose values specify DataFlavors with primary MIME types of
+# "text", and which support the charset parameter, should specify the exact
+# format in which the native platform expects the data. The "charset"
+# parameter specifies the char to byte encoding, the "eoln" parameter
+# specifies the end-of-line marker, and the "terminators" parameter specifies
+# the number of terminating NUL bytes. Note that "eoln" and "terminators"
+# are not standardized MIME type parameters. They are specific to this file
+# format ONLY. They will not appear in any of the DataFlavors returned by the
+# SystemFlavorMap at the Java level.
+#
+# If the "charset" parameter is omitted, or has zero length, the platform
+# default encoding is assumed. If the "eoln" parameter is omitted, or has
+# zero length, "\n" is assumed. If the "terminators" parameter is omitted,
+# or has a value less than zero, zero is assumed.
+#
+# Upon initialization, the data transfer subsystem will record the specified
+# details of the native text format, but the default SystemFlavorMap will
+# present a large set of synthesized DataFlavors which map, in both
+# directions, to the native. After receiving data from the application in one
+# of the synthetic DataFlavors, the data transfer subsystem will transform
+# the data stream into the format specified in this file before passing the
+# transformed stream to the native system.
+#
+# Mappings whose values specify DataFlavors with primary MIME types of
+# "text", but which do not support the charset parameter, will be treated as
+# opaque, 8-bit data. They will not undergo any transformation process, and
+# any "charset", "eoln", or "terminators" parameters specified in this file
+# will be ignored.
+#
+# See java.awt.datatransfer.DataFlavor.selectBestTextFlavor for a list of
+# text flavors which support the charset parameter.
+
+UTF8_STRING=text/plain;charset=UTF-8;eoln="\n";terminators=0
+
+# The COMPOUND_TEXT support for inter-client text transfer is disabled by
+# default. The reason is that many native applications prefer this format over
+# other native text formats, but are unable to decode the textual data in this
+# format properly. This results in java-to-native text transfer failures.
+# To enable the COMPOUND_TEXT support for this JRE installation uncomment
+# the line below.
+
+# COMPOUND_TEXT=text/plain;charset=x-compound-text;eoln="\n";terminators=0
+
+TEXT=text/plain;eoln="\n";terminators=0
+STRING=text/plain;charset=UTF-8;eoln="\n";terminators=0
+FILE_NAME=application/x-java-file-list;class=java.util.List
+text/uri-list=application/x-java-file-list;class=java.util.List
+PNG=image/x-java-image;class=java.awt.Image
+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
--- a/jdk/src/java.desktop/share/classes/java/awt/event/InputMethodEvent.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/classes/java/awt/event/InputMethodEvent.java Wed Jul 05 20:01:44 2017 +0200
@@ -418,7 +418,8 @@
private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
s.defaultReadObject();
if (when == 0) {
- when = getMostRecentEventTimeForSource(this.source);
+ // Can't use getMostRecentEventTimeForSource because source is always null during deserialization
+ when = EventQueue.getMostRecentEventTime();
}
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/JDesktopPane.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JDesktopPane.java Wed Jul 05 20:01:44 2017 +0200
@@ -43,6 +43,7 @@
import java.beans.PropertyVetoException;
import java.util.Set;
import java.util.TreeSet;
+import java.util.LinkedHashSet;
/**
* A container used to create a multiple-document interface or a virtual desktop.
* You create <code>JInternalFrame</code> objects and add them to the
@@ -271,7 +272,7 @@
private static Collection<JInternalFrame> getAllFrames(Container parent) {
int i, count;
- Collection<JInternalFrame> results = new ArrayList<JInternalFrame>();
+ Collection<JInternalFrame> results = new LinkedHashSet<>();
count = parent.getComponentCount();
for (i = 0; i < count; i++) {
Component next = parent.getComponent(i);
--- a/jdk/src/java.desktop/share/classes/sun/java2d/opengl/OGLSurfaceDataProxy.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/opengl/OGLSurfaceDataProxy.java Wed Jul 05 20:01:44 2017 +0200
@@ -65,7 +65,11 @@
int w, int h)
{
if (cachedData == null) {
- cachedData = oglgc.createManagedSurface(w, h, transparency);
+ try {
+ cachedData = oglgc.createManagedSurface(w, h, transparency);
+ } catch (OutOfMemoryError er) {
+ return null;
+ }
}
return cachedData;
}
--- a/jdk/src/java.desktop/share/native/libfontmanager/freetypeScaler.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/libfontmanager/freetypeScaler.c Wed Jul 05 20:01:44 2017 +0200
@@ -1082,86 +1082,60 @@
return 1;
}
-static void addToGP(GPData* gpdata, FT_Outline*outline) {
- jbyte current_type=SEG_UNKNOWN;
- int i, j;
- jfloat x, y;
+static void addSeg(GPData *gp, jbyte type) {
+ gp->pointTypes[gp->numTypes++] = type;
+}
+
+static void addCoords(GPData *gp, FT_Vector *p) {
+ gp->pointCoords[gp->numCoords++] = F26Dot6ToFloat(p->x);
+ gp->pointCoords[gp->numCoords++] = -F26Dot6ToFloat(p->y);
+}
- j = 0;
- for(i=0; i<outline->n_points; i++) {
- x = F26Dot6ToFloat(outline->points[i].x);
- y = -F26Dot6ToFloat(outline->points[i].y);
+static int moveTo(FT_Vector *to, GPData *gp) {
+ if (gp->numCoords)
+ addSeg(gp, SEG_CLOSE);
+ addCoords(gp, to);
+ addSeg(gp, SEG_MOVETO);
+ return FT_Err_Ok;
+}
+
+static int lineTo(FT_Vector *to, GPData *gp) {
+ addCoords(gp, to);
+ addSeg(gp, SEG_LINETO);
+ return FT_Err_Ok;
+}
- if (FT_CURVE_TAG(outline->tags[i]) == FT_CURVE_TAG_ON) {
- /* If bit 0 is unset, the point is "off" the curve,
- i.e., a Bezier control point, while it is "on" when set. */
- if (current_type == SEG_UNKNOWN) { /* special case:
- very first point */
- /* add segment */
- gpdata->pointTypes[gpdata->numTypes++] = SEG_MOVETO;
- current_type = SEG_LINETO;
- } else {
- gpdata->pointTypes[gpdata->numTypes++] = current_type;
- current_type = SEG_LINETO;
- }
- } else {
- if (current_type == SEG_UNKNOWN) { /* special case:
- very first point */
- if (FT_CURVE_TAG(outline->tags[i+1]) == FT_CURVE_TAG_ON) {
- /* just skip first point. Adhoc heuristic? */
- continue;
- } else {
- x = (x + F26Dot6ToFloat(outline->points[i+1].x))/2;
- y = (y - F26Dot6ToFloat(outline->points[i+1].y))/2;
- gpdata->pointTypes[gpdata->numTypes++] = SEG_MOVETO;
- current_type = SEG_LINETO;
- }
- } else if (FT_CURVE_TAG(outline->tags[i]) == FT_CURVE_TAG_CUBIC) {
- /* Bit 1 is meaningful for 'off' points only.
- If set, it indicates a third-order Bezier arc control
- point; and a second-order control point if unset. */
- current_type = SEG_CUBICTO;
- } else {
- /* two successive conic "off" points forces the rasterizer
- to create (during the scan-line conversion process
- exclusively) a virtual "on" point amidst them, at their
- exact middle. This greatly facilitates the definition of
- successive conic Bezier arcs. Moreover, it is the way
- outlines are described in the TrueType specification. */
- if (current_type == SEG_QUADTO) {
- gpdata->pointCoords[gpdata->numCoords++] =
- F26Dot6ToFloat(outline->points[i].x +
- outline->points[i-1].x)/2;
- gpdata->pointCoords[gpdata->numCoords++] =
- - F26Dot6ToFloat(outline->points[i].y +
- outline->points[i-1].y)/2;
- gpdata->pointTypes[gpdata->numTypes++] = SEG_QUADTO;
- }
- current_type = SEG_QUADTO;
- }
- }
- gpdata->pointCoords[gpdata->numCoords++] = x;
- gpdata->pointCoords[gpdata->numCoords++] = y;
- if (outline->contours[j] == i) { //end of contour
- int start = j > 0 ? outline->contours[j-1]+1 : 0;
- gpdata->pointTypes[gpdata->numTypes++] = current_type;
- if (current_type == SEG_QUADTO &&
- FT_CURVE_TAG(outline->tags[start]) != FT_CURVE_TAG_ON) {
- gpdata->pointCoords[gpdata->numCoords++] =
- (F26Dot6ToFloat(outline->points[start].x) + x)/2;
- gpdata->pointCoords[gpdata->numCoords++] =
- (-F26Dot6ToFloat(outline->points[start].y) + y)/2;
- } else {
- gpdata->pointCoords[gpdata->numCoords++] =
- F26Dot6ToFloat(outline->points[start].x);
- gpdata->pointCoords[gpdata->numCoords++] =
- -F26Dot6ToFloat(outline->points[start].y);
- }
- gpdata->pointTypes[gpdata->numTypes++] = SEG_CLOSE;
- current_type = SEG_UNKNOWN;
- j++;
- }
- }
+static int conicTo(FT_Vector *control, FT_Vector *to, GPData *gp) {
+ addCoords(gp, control);
+ addCoords(gp, to);
+ addSeg(gp, SEG_QUADTO);
+ return FT_Err_Ok;
+}
+
+static int cubicTo(FT_Vector *control1,
+ FT_Vector *control2,
+ FT_Vector *to,
+ GPData *gp) {
+ addCoords(gp, control1);
+ addCoords(gp, control2);
+ addCoords(gp, to);
+ addSeg(gp, SEG_CUBICTO);
+ return FT_Err_Ok;
+}
+
+static void addToGP(GPData* gpdata, FT_Outline*outline) {
+ static const FT_Outline_Funcs outline_funcs = {
+ (FT_Outline_MoveToFunc) moveTo,
+ (FT_Outline_LineToFunc) lineTo,
+ (FT_Outline_ConicToFunc) conicTo,
+ (FT_Outline_CubicToFunc) cubicTo,
+ 0, /* shift */
+ 0, /* delta */
+ };
+
+ FT_Outline_Decompose(outline, &outline_funcs, gpdata);
+ if (gpdata->numCoords)
+ addSeg(gpdata, SEG_CLOSE);
/* If set to 1, the outline will be filled using the even-odd fill rule */
if (outline->flags & FT_OUTLINE_EVEN_ODD_FILL) {
--- a/jdk/src/java.desktop/share/native/liblcms/cmscam02.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/cmscam02.c Wed Jul 05 20:01:44 2017 +0200
@@ -467,11 +467,12 @@
CAM02COLOR clr;
cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
- memset(&clr, 0, sizeof(clr));
_cmsAssert(lpMod != NULL);
_cmsAssert(pIn != NULL);
_cmsAssert(pOut != NULL);
+ memset(&clr, 0, sizeof(clr));
+
clr.XYZ[0] = pIn ->X;
clr.XYZ[1] = pIn ->Y;
clr.XYZ[2] = pIn ->Z;
@@ -492,11 +493,12 @@
CAM02COLOR clr;
cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
- memset(&clr, 0, sizeof(clr));
_cmsAssert(lpMod != NULL);
_cmsAssert(pIn != NULL);
_cmsAssert(pOut != NULL);
+ memset(&clr, 0, sizeof(clr));
+
clr.J = pIn -> J;
clr.C = pIn -> C;
clr.h = pIn -> h;
@@ -511,4 +513,3 @@
pOut ->Y = clr.XYZ[1];
pOut ->Z = clr.XYZ[2];
}
-
--- a/jdk/src/java.desktop/share/native/liblcms/cmscgats.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/cmscgats.c Wed Jul 05 20:01:44 2017 +0200
@@ -2179,9 +2179,9 @@
if (cmsstrcasecmp(Fld, "SAMPLE_ID") == 0) {
- t -> SampleID = idField;
-
- for (i=0; i < t -> nPatches; i++) {
+ t -> SampleID = idField;
+
+ for (i=0; i < t -> nPatches; i++) {
char *Data = GetData(it8, i, idField);
if (Data) {
@@ -2196,7 +2196,7 @@
SetData(it8, i, idField, Buffer);
}
- }
+ }
}
--- a/jdk/src/java.desktop/share/native/liblcms/cmscnvrt.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/cmscnvrt.c Wed Jul 05 20:01:44 2017 +0200
@@ -137,15 +137,68 @@
// A pointer to the begining of the list
-static cmsIntentsList *Intents = DefaultIntents;
+_cmsIntentsPluginChunkType _cmsIntentsPluginChunk = { NULL };
+
+// Duplicates the zone of memory used by the plug-in in the new context
+static
+void DupPluginIntentsList(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ _cmsIntentsPluginChunkType newHead = { NULL };
+ cmsIntentsList* entry;
+ cmsIntentsList* Anterior = NULL;
+ _cmsIntentsPluginChunkType* head = (_cmsIntentsPluginChunkType*) src->chunks[IntentPlugin];
+
+ // Walk the list copying all nodes
+ for (entry = head->Intents;
+ entry != NULL;
+ entry = entry ->Next) {
+
+ cmsIntentsList *newEntry = ( cmsIntentsList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(cmsIntentsList));
+
+ if (newEntry == NULL)
+ return;
+
+ // We want to keep the linked list order, so this is a little bit tricky
+ newEntry -> Next = NULL;
+ if (Anterior)
+ Anterior -> Next = newEntry;
+
+ Anterior = newEntry;
+
+ if (newHead.Intents == NULL)
+ newHead.Intents = newEntry;
+ }
+
+ ctx ->chunks[IntentPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsIntentsPluginChunkType));
+}
+
+void _cmsAllocIntentsPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ if (src != NULL) {
+
+ // Copy all linked list
+ DupPluginIntentsList(ctx, src);
+ }
+ else {
+ static _cmsIntentsPluginChunkType IntentsPluginChunkType = { NULL };
+ ctx ->chunks[IntentPlugin] = _cmsSubAllocDup(ctx ->MemPool, &IntentsPluginChunkType, sizeof(_cmsIntentsPluginChunkType));
+ }
+}
+
// Search the list for a suitable intent. Returns NULL if not found
static
-cmsIntentsList* SearchIntent(cmsUInt32Number Intent)
+cmsIntentsList* SearchIntent(cmsContext ContextID, cmsUInt32Number Intent)
{
+ _cmsIntentsPluginChunkType* ctx = ( _cmsIntentsPluginChunkType*) _cmsContextGetClientChunk(ContextID, IntentPlugin);
cmsIntentsList* pt;
- for (pt = Intents; pt != NULL; pt = pt -> Next)
+ for (pt = ctx -> Intents; pt != NULL; pt = pt -> Next)
+ if (pt ->Intent == Intent) return pt;
+
+ for (pt = DefaultIntents; pt != NULL; pt = pt -> Next)
if (pt ->Intent == Intent) return pt;
return NULL;
@@ -1031,7 +1084,7 @@
// this case would present some issues if the custom intent tries to do things like
// preserve primaries. This solution is not perfect, but works well on most cases.
- Intent = SearchIntent(TheIntents[0]);
+ Intent = SearchIntent(ContextID, TheIntents[0]);
if (Intent == NULL) {
cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported intent '%d'", TheIntents[0]);
return NULL;
@@ -1046,12 +1099,14 @@
// Get information about available intents. nMax is the maximum space for the supplied "Codes"
// and "Descriptions" the function returns the total number of intents, which may be greater
// than nMax, although the matrices are not populated beyond this level.
-cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions)
+cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID, cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions)
{
+ _cmsIntentsPluginChunkType* ctx = ( _cmsIntentsPluginChunkType*) _cmsContextGetClientChunk(ContextID, IntentPlugin);
cmsIntentsList* pt;
cmsUInt32Number nIntents;
- for (nIntents=0, pt = Intents; pt != NULL; pt = pt -> Next)
+
+ for (nIntents=0, pt = ctx->Intents; pt != NULL; pt = pt -> Next)
{
if (nIntents < nMax) {
if (Codes != NULL)
@@ -1064,37 +1119,52 @@
nIntents++;
}
+ for (nIntents=0, pt = DefaultIntents; pt != NULL; pt = pt -> Next)
+ {
+ if (nIntents < nMax) {
+ if (Codes != NULL)
+ Codes[nIntents] = pt ->Intent;
+
+ if (Descriptions != NULL)
+ Descriptions[nIntents] = pt ->Description;
+ }
+
+ nIntents++;
+ }
return nIntents;
}
+cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions)
+{
+ return cmsGetSupportedIntentsTHR(NULL, nMax, Codes, Descriptions);
+}
+
// The plug-in registration. User can add new intents or override default routines
cmsBool _cmsRegisterRenderingIntentPlugin(cmsContext id, cmsPluginBase* Data)
{
+ _cmsIntentsPluginChunkType* ctx = ( _cmsIntentsPluginChunkType*) _cmsContextGetClientChunk(id, IntentPlugin);
cmsPluginRenderingIntent* Plugin = (cmsPluginRenderingIntent*) Data;
cmsIntentsList* fl;
- // Do we have to reset the intents?
+ // Do we have to reset the custom intents?
if (Data == NULL) {
- Intents = DefaultIntents;
- return TRUE;
+ ctx->Intents = NULL;
+ return TRUE;
}
- fl = SearchIntent(Plugin ->Intent);
+ fl = (cmsIntentsList*) _cmsPluginMalloc(id, sizeof(cmsIntentsList));
+ if (fl == NULL) return FALSE;
- if (fl == NULL) {
- fl = (cmsIntentsList*) _cmsPluginMalloc(id, sizeof(cmsIntentsList));
- if (fl == NULL) return FALSE;
- }
fl ->Intent = Plugin ->Intent;
- strncpy(fl ->Description, Plugin ->Description, 255);
- fl ->Description[255] = 0;
+ strncpy(fl ->Description, Plugin ->Description, sizeof(fl ->Description)-1);
+ fl ->Description[sizeof(fl ->Description)-1] = 0;
fl ->Link = Plugin ->Link;
- fl ->Next = Intents;
- Intents = fl;
+ fl ->Next = ctx ->Intents;
+ ctx ->Intents = fl;
return TRUE;
}
--- a/jdk/src/java.desktop/share/native/liblcms/cmserr.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/cmserr.c Wed Jul 05 20:01:44 2017 +0200
@@ -60,13 +60,14 @@
// compare two strings ignoring case
int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2)
{
- register const unsigned char *us1 = (const unsigned char *)s1,
- *us2 = (const unsigned char *)s2;
+ register const unsigned char *us1 = (const unsigned char *)s1,
+ *us2 = (const unsigned char *)s2;
- while (toupper(*us1) == toupper(*us2++))
- if (*us1++ == '\0')
- return (0);
- return (toupper(*us1) - toupper(*--us2));
+ while (toupper(*us1) == toupper(*us2++))
+ if (*us1++ == '\0')
+ return 0;
+
+ return (toupper(*us1) - toupper(*--us2));
}
// long int because C99 specifies ftell in such way (7.19.9.2)
@@ -91,9 +92,8 @@
//
// This is the interface to low-level memory management routines. By default a simple
// wrapping to malloc/free/realloc is provided, although there is a limit on the max
-// amount of memoy that can be reclaimed. This is mostly as a safety feature to
-// prevent bogus or malintentionated code to allocate huge blocks that otherwise lcms
-// would never need.
+// amount of memoy that can be reclaimed. This is mostly as a safety feature to prevent
+// bogus or evil code to allocate huge blocks that otherwise lcms would never need.
#define MAX_MEMORY_FOR_ALLOC ((cmsUInt32Number)(1024U*1024U*512U))
@@ -103,7 +103,7 @@
// required to be implemented: malloc, realloc and free, although the user may want to
// replace the optional mallocZero, calloc and dup as well.
-cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin);
+cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// *********************************************************************************
@@ -143,7 +143,7 @@
cmsUNUSED_PARAMETER(ContextID);
}
-// The default realloc function. Again it check for exploits. If Ptr is NULL,
+// The default realloc function. Again it checks for exploits. If Ptr is NULL,
// realloc behaves the same way as malloc and allocates a new block of size bytes.
static
void* _cmsReallocDefaultFn(cmsContext ContextID, void* Ptr, cmsUInt32Number size)
@@ -196,28 +196,73 @@
return mem;
}
-// Pointers to malloc and _cmsFree functions in current environment
-static void * (* MallocPtr)(cmsContext ContextID, cmsUInt32Number size) = _cmsMallocDefaultFn;
-static void * (* MallocZeroPtr)(cmsContext ContextID, cmsUInt32Number size) = _cmsMallocZeroDefaultFn;
-static void (* FreePtr)(cmsContext ContextID, void *Ptr) = _cmsFreeDefaultFn;
-static void * (* ReallocPtr)(cmsContext ContextID, void *Ptr, cmsUInt32Number NewSize) = _cmsReallocDefaultFn;
-static void * (* CallocPtr)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size)= _cmsCallocDefaultFn;
-static void * (* DupPtr)(cmsContext ContextID, const void* Org, cmsUInt32Number size) = _cmsDupDefaultFn;
+
+// Pointers to memory manager functions in Context0
+_cmsMemPluginChunkType _cmsMemPluginChunk = { _cmsMallocDefaultFn, _cmsMallocZeroDefaultFn, _cmsFreeDefaultFn,
+ _cmsReallocDefaultFn, _cmsCallocDefaultFn, _cmsDupDefaultFn
+ };
+
+
+// Reset and duplicate memory manager
+void _cmsAllocMemPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src)
+{
+ _cmsAssert(ctx != NULL);
+
+ if (src != NULL) {
+
+ // Duplicate
+ ctx ->chunks[MemPlugin] = _cmsSubAllocDup(ctx ->MemPool, src ->chunks[MemPlugin], sizeof(_cmsMemPluginChunkType));
+ }
+ else {
+
+ // To reset it, we use the default allocators, which cannot be overriden
+ ctx ->chunks[MemPlugin] = &ctx ->DefaultMemoryManager;
+ }
+}
+
+// Auxiliar to fill memory management functions from plugin (or context 0 defaults)
+void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkType* ptr)
+{
+ if (Plugin == NULL) {
+
+ memcpy(ptr, &_cmsMemPluginChunk, sizeof(_cmsMemPluginChunk));
+ }
+ else {
+
+ ptr ->MallocPtr = Plugin -> MallocPtr;
+ ptr ->FreePtr = Plugin -> FreePtr;
+ ptr ->ReallocPtr = Plugin -> ReallocPtr;
+
+ // Make sure we revert to defaults
+ ptr ->MallocZeroPtr= _cmsMallocZeroDefaultFn;
+ ptr ->CallocPtr = _cmsCallocDefaultFn;
+ ptr ->DupPtr = _cmsDupDefaultFn;
+
+ if (Plugin ->MallocZeroPtr != NULL) ptr ->MallocZeroPtr = Plugin -> MallocZeroPtr;
+ if (Plugin ->CallocPtr != NULL) ptr ->CallocPtr = Plugin -> CallocPtr;
+ if (Plugin ->DupPtr != NULL) ptr ->DupPtr = Plugin -> DupPtr;
+
+ }
+}
+
// Plug-in replacement entry
-cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase *Data)
+cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase *Data)
{
cmsPluginMemHandler* Plugin = (cmsPluginMemHandler*) Data;
+ _cmsMemPluginChunkType* ptr;
- // NULL forces to reset to defaults
+ // NULL forces to reset to defaults. In this special case, the defaults are stored in the context structure.
+ // Remaining plug-ins does NOT have any copy in the context structure, but this is somehow special as the
+ // context internal data should be malloce'd by using those functions.
if (Data == NULL) {
- MallocPtr = _cmsMallocDefaultFn;
- MallocZeroPtr= _cmsMallocZeroDefaultFn;
- FreePtr = _cmsFreeDefaultFn;
- ReallocPtr = _cmsReallocDefaultFn;
- CallocPtr = _cmsCallocDefaultFn;
- DupPtr = _cmsDupDefaultFn;
+ struct _cmsContext_struct* ctx = ( struct _cmsContext_struct*) ContextID;
+
+ // Return to the default allocators
+ if (ContextID != NULL) {
+ ctx->chunks[MemPlugin] = (void*) &ctx->DefaultMemoryManager;
+ }
return TRUE;
}
@@ -227,51 +272,56 @@
Plugin -> ReallocPtr == NULL) return FALSE;
// Set replacement functions
- MallocPtr = Plugin -> MallocPtr;
- FreePtr = Plugin -> FreePtr;
- ReallocPtr = Plugin -> ReallocPtr;
+ ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
+ if (ptr == NULL)
+ return FALSE;
- if (Plugin ->MallocZeroPtr != NULL) MallocZeroPtr = Plugin ->MallocZeroPtr;
- if (Plugin ->CallocPtr != NULL) CallocPtr = Plugin -> CallocPtr;
- if (Plugin ->DupPtr != NULL) DupPtr = Plugin -> DupPtr;
-
+ _cmsInstallAllocFunctions(Plugin, ptr);
return TRUE;
}
// Generic allocate
void* CMSEXPORT _cmsMalloc(cmsContext ContextID, cmsUInt32Number size)
{
- return MallocPtr(ContextID, size);
+ _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
+ return ptr ->MallocPtr(ContextID, size);
}
// Generic allocate & zero
void* CMSEXPORT _cmsMallocZero(cmsContext ContextID, cmsUInt32Number size)
{
- return MallocZeroPtr(ContextID, size);
+ _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
+ return ptr->MallocZeroPtr(ContextID, size);
}
// Generic calloc
void* CMSEXPORT _cmsCalloc(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size)
{
- return CallocPtr(ContextID, num, size);
+ _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
+ return ptr->CallocPtr(ContextID, num, size);
}
// Generic reallocate
void* CMSEXPORT _cmsRealloc(cmsContext ContextID, void* Ptr, cmsUInt32Number size)
{
- return ReallocPtr(ContextID, Ptr, size);
+ _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
+ return ptr->ReallocPtr(ContextID, Ptr, size);
}
// Generic free memory
void CMSEXPORT _cmsFree(cmsContext ContextID, void* Ptr)
{
- if (Ptr != NULL) FreePtr(ContextID, Ptr);
+ if (Ptr != NULL) {
+ _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
+ ptr ->FreePtr(ContextID, Ptr);
+ }
}
// Generic block duplication
void* CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Number size)
{
- return DupPtr(ContextID, Org, size);
+ _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
+ return ptr ->DupPtr(ContextID, Org, size);
}
// ********************************************************************************************
@@ -380,6 +430,26 @@
return (void*) ptr;
}
+// Duplicate in pool
+void* _cmsSubAllocDup(_cmsSubAllocator* s, const void *ptr, cmsUInt32Number size)
+{
+ void *NewPtr;
+
+ // Dup of null pointer is also NULL
+ if (ptr == NULL)
+ return NULL;
+
+ NewPtr = _cmsSubAlloc(s, size);
+
+ if (ptr != NULL && NewPtr != NULL) {
+ memcpy(NewPtr, ptr, size);
+ }
+
+ return NewPtr;
+}
+
+
+
// Error logging ******************************************************************
// There is no error handling at all. When a funtion fails, it returns proper value.
@@ -401,8 +471,26 @@
// This is our default log error
static void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text);
-// The current handler in actual environment
-static cmsLogErrorHandlerFunction LogErrorHandler = DefaultLogErrorHandlerFunction;
+// Context0 storage, which is global
+_cmsLogErrorChunkType _cmsLogErrorChunk = { DefaultLogErrorHandlerFunction };
+
+// Allocates and inits error logger container for a given context. If src is NULL, only initializes the value
+// to the default. Otherwise, it duplicates the value. The interface is standard across all context clients
+void _cmsAllocLogErrorChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ static _cmsLogErrorChunkType LogErrorChunk = { DefaultLogErrorHandlerFunction };
+ void* from;
+
+ if (src != NULL) {
+ from = src ->chunks[Logger];
+ }
+ else {
+ from = &LogErrorChunk;
+ }
+
+ ctx ->chunks[Logger] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsLogErrorChunkType));
+}
// The default error logger does nothing.
static
@@ -416,13 +504,24 @@
cmsUNUSED_PARAMETER(Text);
}
-// Change log error
+// Change log error, context based
+void CMSEXPORT cmsSetLogErrorHandlerTHR(cmsContext ContextID, cmsLogErrorHandlerFunction Fn)
+{
+ _cmsLogErrorChunkType* lhg = (_cmsLogErrorChunkType*) _cmsContextGetClientChunk(ContextID, Logger);
+
+ if (lhg != NULL) {
+
+ if (Fn == NULL)
+ lhg -> LogErrorHandler = DefaultLogErrorHandlerFunction;
+ else
+ lhg -> LogErrorHandler = Fn;
+ }
+}
+
+// Change log error, legacy
void CMSEXPORT cmsSetLogErrorHandler(cmsLogErrorHandlerFunction Fn)
{
- if (Fn == NULL)
- LogErrorHandler = DefaultLogErrorHandlerFunction;
- else
- LogErrorHandler = Fn;
+ cmsSetLogErrorHandlerTHR(NULL, Fn);
}
// Log an error
@@ -431,13 +530,18 @@
{
va_list args;
char Buffer[MAX_ERROR_MESSAGE_LEN];
+ _cmsLogErrorChunkType* lhg;
+
va_start(args, ErrorText);
vsnprintf(Buffer, MAX_ERROR_MESSAGE_LEN-1, ErrorText, args);
va_end(args);
- // Call handler
- LogErrorHandler(ContextID, ErrorCode, Buffer);
+ // Check for the context, if specified go there. If not, go for the global
+ lhg = (_cmsLogErrorChunkType*) _cmsContextGetClientChunk(ContextID, Logger);
+ if (lhg ->LogErrorHandler) {
+ lhg ->LogErrorHandler(ContextID, ErrorCode, Buffer);
+ }
}
// Utility function to print signatures
@@ -455,3 +559,125 @@
String[4] = 0;
}
+//--------------------------------------------------------------------------------------------------
+
+
+static
+void* defMtxCreate(cmsContext id)
+{
+ _cmsMutex* ptr_mutex = (_cmsMutex*) _cmsMalloc(id, sizeof(_cmsMutex));
+ _cmsInitMutexPrimitive(ptr_mutex);
+ return (void*) ptr_mutex;
+}
+
+static
+void defMtxDestroy(cmsContext id, void* mtx)
+{
+ _cmsDestroyMutexPrimitive((_cmsMutex *) mtx);
+ _cmsFree(id, mtx);
+}
+
+static
+cmsBool defMtxLock(cmsContext id, void* mtx)
+{
+ cmsUNUSED_PARAMETER(id);
+ return _cmsLockPrimitive((_cmsMutex *) mtx) == 0;
+}
+
+static
+void defMtxUnlock(cmsContext id, void* mtx)
+{
+ cmsUNUSED_PARAMETER(id);
+ _cmsUnlockPrimitive((_cmsMutex *) mtx);
+}
+
+
+
+// Pointers to memory manager functions in Context0
+_cmsMutexPluginChunkType _cmsMutexPluginChunk = { defMtxCreate, defMtxDestroy, defMtxLock, defMtxUnlock };
+
+// Allocate and init mutex container.
+void _cmsAllocMutexPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ static _cmsMutexPluginChunkType MutexChunk = {defMtxCreate, defMtxDestroy, defMtxLock, defMtxUnlock };
+ void* from;
+
+ if (src != NULL) {
+ from = src ->chunks[MutexPlugin];
+ }
+ else {
+ from = &MutexChunk;
+ }
+
+ ctx ->chunks[MutexPlugin] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsMutexPluginChunkType));
+}
+
+// Register new ways to transform
+cmsBool _cmsRegisterMutexPlugin(cmsContext ContextID, cmsPluginBase* Data)
+{
+ cmsPluginMutex* Plugin = (cmsPluginMutex*) Data;
+ _cmsMutexPluginChunkType* ctx = ( _cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
+
+ if (Data == NULL) {
+
+ // No lock routines
+ ctx->CreateMutexPtr = NULL;
+ ctx->DestroyMutexPtr = NULL;
+ ctx->LockMutexPtr = NULL;
+ ctx ->UnlockMutexPtr = NULL;
+ return TRUE;
+ }
+
+ // Factory callback is required
+ if (Plugin ->CreateMutexPtr == NULL || Plugin ->DestroyMutexPtr == NULL ||
+ Plugin ->LockMutexPtr == NULL || Plugin ->UnlockMutexPtr == NULL) return FALSE;
+
+
+ ctx->CreateMutexPtr = Plugin->CreateMutexPtr;
+ ctx->DestroyMutexPtr = Plugin ->DestroyMutexPtr;
+ ctx ->LockMutexPtr = Plugin ->LockMutexPtr;
+ ctx ->UnlockMutexPtr = Plugin ->UnlockMutexPtr;
+
+ // All is ok
+ return TRUE;
+}
+
+// Generic Mutex fns
+void* CMSEXPORT _cmsCreateMutex(cmsContext ContextID)
+{
+ _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
+
+ if (ptr ->CreateMutexPtr == NULL) return NULL;
+
+ return ptr ->CreateMutexPtr(ContextID);
+}
+
+void CMSEXPORT _cmsDestroyMutex(cmsContext ContextID, void* mtx)
+{
+ _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
+
+ if (ptr ->DestroyMutexPtr != NULL) {
+
+ ptr ->DestroyMutexPtr(ContextID, mtx);
+ }
+}
+
+cmsBool CMSEXPORT _cmsLockMutex(cmsContext ContextID, void* mtx)
+{
+ _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
+
+ if (ptr ->LockMutexPtr == NULL) return TRUE;
+
+ return ptr ->LockMutexPtr(ContextID, mtx);
+}
+
+void CMSEXPORT _cmsUnlockMutex(cmsContext ContextID, void* mtx)
+{
+ _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
+
+ if (ptr ->UnlockMutexPtr != NULL) {
+
+ ptr ->UnlockMutexPtr(ContextID, mtx);
+ }
+}
--- a/jdk/src/java.desktop/share/native/liblcms/cmsgamma.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/cmsgamma.c Wed Jul 05 20:01:44 2017 +0200
@@ -82,7 +82,6 @@
} _cmsParametricCurvesCollection;
-
// This is the default (built-in) evaluator
static cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Number Params[], cmsFloat64Number R);
@@ -95,22 +94,77 @@
NULL // Next in chain
};
+// Duplicates the zone of memory used by the plug-in in the new context
+static
+void DupPluginCurvesList(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ _cmsCurvesPluginChunkType newHead = { NULL };
+ _cmsParametricCurvesCollection* entry;
+ _cmsParametricCurvesCollection* Anterior = NULL;
+ _cmsCurvesPluginChunkType* head = (_cmsCurvesPluginChunkType*) src->chunks[CurvesPlugin];
+
+ _cmsAssert(head != NULL);
+
+ // Walk the list copying all nodes
+ for (entry = head->ParametricCurves;
+ entry != NULL;
+ entry = entry ->Next) {
+
+ _cmsParametricCurvesCollection *newEntry = ( _cmsParametricCurvesCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsParametricCurvesCollection));
+
+ if (newEntry == NULL)
+ return;
+
+ // We want to keep the linked list order, so this is a little bit tricky
+ newEntry -> Next = NULL;
+ if (Anterior)
+ Anterior -> Next = newEntry;
+
+ Anterior = newEntry;
+
+ if (newHead.ParametricCurves == NULL)
+ newHead.ParametricCurves = newEntry;
+ }
+
+ ctx ->chunks[CurvesPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsCurvesPluginChunkType));
+}
+
+// The allocator have to follow the chain
+void _cmsAllocCurvesPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ _cmsAssert(ctx != NULL);
+
+ if (src != NULL) {
+
+ // Copy all linked list
+ DupPluginCurvesList(ctx, src);
+ }
+ else {
+ static _cmsCurvesPluginChunkType CurvesPluginChunk = { NULL };
+ ctx ->chunks[CurvesPlugin] = _cmsSubAllocDup(ctx ->MemPool, &CurvesPluginChunk, sizeof(_cmsCurvesPluginChunkType));
+ }
+}
+
+
// The linked list head
-static _cmsParametricCurvesCollection* ParametricCurves = &DefaultCurves;
+_cmsCurvesPluginChunkType _cmsCurvesPluginChunk = { NULL };
// As a way to install new parametric curves
-cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext id, cmsPluginBase* Data)
+cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext ContextID, cmsPluginBase* Data)
{
+ _cmsCurvesPluginChunkType* ctx = ( _cmsCurvesPluginChunkType*) _cmsContextGetClientChunk(ContextID, CurvesPlugin);
cmsPluginParametricCurves* Plugin = (cmsPluginParametricCurves*) Data;
_cmsParametricCurvesCollection* fl;
if (Data == NULL) {
- ParametricCurves = &DefaultCurves;
+ ctx -> ParametricCurves = NULL;
return TRUE;
}
- fl = (_cmsParametricCurvesCollection*) _cmsPluginMalloc(id, sizeof(_cmsParametricCurvesCollection));
+ fl = (_cmsParametricCurvesCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsParametricCurvesCollection));
if (fl == NULL) return FALSE;
// Copy the parameters
@@ -126,8 +180,8 @@
memmove(fl->ParameterCount, Plugin ->ParameterCount, fl->nFunctions * sizeof(cmsUInt32Number));
// Keep linked list
- fl ->Next = ParametricCurves;
- ParametricCurves = fl;
+ fl ->Next = ctx->ParametricCurves;
+ ctx->ParametricCurves = fl;
// All is ok
return TRUE;
@@ -149,12 +203,24 @@
// Search for the collection which contains a specific type
static
-_cmsParametricCurvesCollection *GetParametricCurveByType(int Type, int* index)
+_cmsParametricCurvesCollection *GetParametricCurveByType(cmsContext ContextID, int Type, int* index)
{
_cmsParametricCurvesCollection* c;
int Position;
+ _cmsCurvesPluginChunkType* ctx = ( _cmsCurvesPluginChunkType*) _cmsContextGetClientChunk(ContextID, CurvesPlugin);
- for (c = ParametricCurves; c != NULL; c = c ->Next) {
+ for (c = ctx->ParametricCurves; c != NULL; c = c ->Next) {
+
+ Position = IsInSet(Type, c);
+
+ if (Position != -1) {
+ if (index != NULL)
+ *index = Position;
+ return c;
+ }
+ }
+ // If none found, revert for defaults
+ for (c = &DefaultCurves; c != NULL; c = c ->Next) {
Position = IsInSet(Type, c);
@@ -251,7 +317,7 @@
p ->Segments[i].SampledPoints = NULL;
- c = GetParametricCurveByType(Segments[i].Type, NULL);
+ c = GetParametricCurveByType(ContextID, Segments[i].Type, NULL);
if (c != NULL)
p ->Evals[i] = c ->Evaluator;
}
@@ -677,12 +743,12 @@
cmsCurveSegment Seg0;
int Pos = 0;
cmsUInt32Number size;
- _cmsParametricCurvesCollection* c = GetParametricCurveByType(Type, &Pos);
+ _cmsParametricCurvesCollection* c = GetParametricCurveByType(ContextID, Type, &Pos);
_cmsAssert(Params != NULL);
if (c == NULL) {
- cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Invalid parametric curve type %d", Type);
+ cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Invalid parametric curve type %d", Type);
return NULL;
}
@@ -872,7 +938,10 @@
_cmsAssert(InCurve != NULL);
// Try to reverse it analytically whatever possible
- if (InCurve ->nSegments == 1 && InCurve ->Segments[0].Type > 0 && InCurve -> Segments[0].Type <= 5) {
+
+ if (InCurve ->nSegments == 1 && InCurve ->Segments[0].Type > 0 &&
+ /* InCurve -> Segments[0].Type <= 5 */
+ GetParametricCurveByType(InCurve ->InterpParams->ContextID, InCurve ->Segments[0].Type, NULL) != NULL) {
return cmsBuildParametricToneCurve(InCurve ->InterpParams->ContextID,
-(InCurve -> Segments[0].Type),
--- a/jdk/src/java.desktop/share/native/liblcms/cmsgmt.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/cmsgmt.c Wed Jul 05 20:01:44 2017 +0200
@@ -191,7 +191,7 @@
out = ComputeKToLstar(ContextID, nPoints, 1,
Intents + (nProfiles - 1),
- hProfiles + (nProfiles - 1),
+ &hProfiles [nProfiles - 1],
BPC + (nProfiles - 1),
AdaptationStates + (nProfiles - 1),
dwFlags);
--- a/jdk/src/java.desktop/share/native/liblcms/cmsintrp.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/cmsintrp.c Wed Jul 05 20:01:44 2017 +0200
@@ -62,31 +62,57 @@
static cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags);
// This is the default factory
-static cmsInterpFnFactory Interpolators = DefaultInterpolatorsFactory;
+_cmsInterpPluginChunkType _cmsInterpPluginChunk = { NULL };
+
+// The interpolation plug-in memory chunk allocator/dup
+void _cmsAllocInterpPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src)
+{
+ void* from;
+
+ _cmsAssert(ctx != NULL);
+
+ if (src != NULL) {
+ from = src ->chunks[InterpPlugin];
+ }
+ else {
+ static _cmsInterpPluginChunkType InterpPluginChunk = { NULL };
+
+ from = &InterpPluginChunk;
+ }
+
+ _cmsAssert(from != NULL);
+ ctx ->chunks[InterpPlugin] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsInterpPluginChunkType));
+}
// Main plug-in entry
-cmsBool _cmsRegisterInterpPlugin(cmsPluginBase* Data)
+cmsBool _cmsRegisterInterpPlugin(cmsContext ContextID, cmsPluginBase* Data)
{
cmsPluginInterpolation* Plugin = (cmsPluginInterpolation*) Data;
+ _cmsInterpPluginChunkType* ptr = (_cmsInterpPluginChunkType*) _cmsContextGetClientChunk(ContextID, InterpPlugin);
if (Data == NULL) {
- Interpolators = DefaultInterpolatorsFactory;
+ ptr ->Interpolators = NULL;
return TRUE;
}
// Set replacement functions
- Interpolators = Plugin ->InterpolatorsFactory;
+ ptr ->Interpolators = Plugin ->InterpolatorsFactory;
return TRUE;
}
// Set the interpolation method
-cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p)
+cmsBool _cmsSetInterpolationRoutine(cmsContext ContextID, cmsInterpParams* p)
{
- // Invoke factory, possibly in the Plug-in
- p ->Interpolation = Interpolators(p -> nInputs, p ->nOutputs, p ->dwFlags);
+ _cmsInterpPluginChunkType* ptr = (_cmsInterpPluginChunkType*) _cmsContextGetClientChunk(ContextID, InterpPlugin);
+
+ p ->Interpolation.Lerp16 = NULL;
+
+ // Invoke factory, possibly in the Plug-in
+ if (ptr ->Interpolators != NULL)
+ p ->Interpolation = ptr->Interpolators(p -> nInputs, p ->nOutputs, p ->dwFlags);
// If unsupported by the plug-in, go for the LittleCMS default.
// If happens only if an extern plug-in is being used
@@ -97,6 +123,7 @@
if (p ->Interpolation.Lerp16 == NULL) {
return FALSE;
}
+
return TRUE;
}
@@ -141,7 +168,7 @@
p ->opta[i] = p ->opta[i-1] * nSamples[InputChan-i];
- if (!_cmsSetInterpolationRoutine(p)) {
+ if (!_cmsSetInterpolationRoutine(ContextID, p)) {
cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported interpolation (%d->%d channels)", InputChan, OutputChan);
_cmsFree(ContextID, p);
return NULL;
--- a/jdk/src/java.desktop/share/native/liblcms/cmsio0.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/cmsio0.c Wed Jul 05 20:01:44 2017 +0200
@@ -229,15 +229,14 @@
if (ResData == NULL) return FALSE; // Housekeeping
// Check for available space. Clip.
- if (iohandler ->UsedSpace + size > ResData->Size) {
- size = ResData ->Size - iohandler ->UsedSpace;
+ if (ResData->Pointer + size > ResData->Size) {
+ size = ResData ->Size - ResData->Pointer;
}
if (size == 0) return TRUE; // Write zero bytes is ok, but does nothing
memmove(ResData ->Block + ResData ->Pointer, Ptr, size);
ResData ->Pointer += size;
- iohandler->UsedSpace += size;
if (ResData ->Pointer > iohandler->UsedSpace)
iohandler->UsedSpace = ResData ->Pointer;
@@ -371,7 +370,7 @@
static
cmsUInt32Number FileTell(cmsIOHANDLER* iohandler)
{
- return ftell((FILE*)iohandler ->stream);
+ return (cmsUInt32Number) ftell((FILE*)iohandler ->stream);
}
// Writes data to stream, also keeps used space for further reference. Returns TRUE on success, FALSE on error
@@ -414,7 +413,7 @@
cmsSignalError(ContextID, cmsERROR_FILE, "File '%s' not found", FileName);
return NULL;
}
- iohandler -> ReportedSize = cmsfilelength(fm);
+ iohandler -> ReportedSize = (cmsUInt32Number) cmsfilelength(fm);
break;
case 'w':
@@ -461,7 +460,7 @@
iohandler -> ContextID = ContextID;
iohandler -> stream = (void*) Stream;
iohandler -> UsedSpace = 0;
- iohandler -> ReportedSize = cmsfilelength(Stream);
+ iohandler -> ReportedSize = (cmsUInt32Number) cmsfilelength(Stream);
iohandler -> PhysicalFile[0] = 0;
iohandler ->Read = FileRead;
@@ -501,6 +500,9 @@
// Set creation date/time
memmove(&Icc ->Created, gmtime(&now), sizeof(Icc ->Created));
+ // Create a mutex if the user provided proper plugin. NULL otherwise
+ Icc ->UsrMutex = _cmsCreateMutex(ContextID);
+
// Return the handle
return (cmsHPROFILE) Icc;
}
@@ -579,9 +581,39 @@
return n;
}
+// Deletes a tag entry
-// Create a new tag entry
+static
+void _cmsDeleteTagByPos(_cmsICCPROFILE* Icc, int i)
+{
+ _cmsAssert(Icc != NULL);
+ _cmsAssert(i >= 0);
+
+
+ if (Icc -> TagPtrs[i] != NULL) {
+
+ // Free previous version
+ if (Icc ->TagSaveAsRaw[i]) {
+ _cmsFree(Icc ->ContextID, Icc ->TagPtrs[i]);
+ }
+ else {
+ cmsTagTypeHandler* TypeHandler = Icc ->TagTypeHandlers[i];
+ if (TypeHandler != NULL) {
+
+ cmsTagTypeHandler LocalTypeHandler = *TypeHandler;
+ LocalTypeHandler.ContextID = Icc ->ContextID; // As an additional parameter
+ LocalTypeHandler.ICCVersion = Icc ->Version;
+ LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc -> TagPtrs[i]);
+ Icc ->TagPtrs[i] = NULL;
+ }
+ }
+
+ }
+}
+
+
+// Creates a new tag entry
static
cmsBool _cmsNewTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, int* NewPos)
{
@@ -589,15 +621,15 @@
// Search for the tag
i = _cmsSearchTag(Icc, sig, FALSE);
+ if (i >= 0) {
- // Now let's do it easy. If the tag has been already written, that's an error
- if (i >= 0) {
- cmsSignalError(Icc ->ContextID, cmsERROR_ALREADY_DEFINED, "Tag '%x' already exists", sig);
- return FALSE;
+ // Already exists? delete it
+ _cmsDeleteTagByPos(Icc, i);
+ *NewPos = i;
}
else {
- // New one
+ // No, make a new one
if (Icc -> TagCount >= MAX_TABLE_TAG) {
cmsSignalError(Icc ->ContextID, cmsERROR_RANGE, "Too many tags (%d)", MAX_TABLE_TAG);
@@ -979,7 +1011,7 @@
// 4.2 -> 0x4200000
- Icc -> Version = BaseToBase((cmsUInt32Number) floor(Version * 100.0), 10, 16) << 16;
+ Icc -> Version = BaseToBase((cmsUInt32Number) floor(Version * 100.0 + 0.5), 10, 16) << 16;
}
cmsFloat64Number CMSEXPORT cmsGetProfileVersion(cmsHPROFILE hProfile)
@@ -1011,6 +1043,32 @@
return NULL;
}
+// Create profile from IOhandler
+cmsHPROFILE CMSEXPORT cmsOpenProfileFromIOhandler2THR(cmsContext ContextID, cmsIOHANDLER* io, cmsBool write)
+{
+ _cmsICCPROFILE* NewIcc;
+ cmsHPROFILE hEmpty = cmsCreateProfilePlaceholder(ContextID);
+
+ if (hEmpty == NULL) return NULL;
+
+ NewIcc = (_cmsICCPROFILE*) hEmpty;
+
+ NewIcc ->IOhandler = io;
+ if (write) {
+
+ NewIcc -> IsWrite = TRUE;
+ return hEmpty;
+ }
+
+ if (!_cmsReadHeader(NewIcc)) goto Error;
+ return hEmpty;
+
+Error:
+ cmsCloseProfile(hEmpty);
+ return NULL;
+}
+
+
// Create profile from disk file
cmsHPROFILE CMSEXPORT cmsOpenProfileFromFileTHR(cmsContext ContextID, const char *lpFileName, const char *sAccess)
{
@@ -1202,7 +1260,7 @@
else {
// Search for support on this tag
- TagDescriptor = _cmsGetTagDescriptor(Icc -> TagNames[i]);
+ TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, Icc -> TagNames[i]);
if (TagDescriptor == NULL) continue; // Unsupported, ignore it
if (TagDescriptor ->DecideType != NULL) {
@@ -1214,7 +1272,7 @@
Type = TagDescriptor ->SupportedTypes[0];
}
- TypeHandler = _cmsGetTagTypeHandler(Type);
+ TypeHandler = _cmsGetTagTypeHandler(Icc->ContextID, Type);
if (TypeHandler == NULL) {
cmsSignalError(Icc ->ContextID, cmsERROR_INTERNAL, "(Internal) no handler for tag %x", Icc -> TagNames[i]);
@@ -1282,10 +1340,12 @@
{
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
_cmsICCPROFILE Keep;
- cmsIOHANDLER* PrevIO;
+ cmsIOHANDLER* PrevIO = NULL;
cmsUInt32Number UsedSpace;
cmsContext ContextID;
+ _cmsAssert(hProfile != NULL);
+
memmove(&Keep, Icc, sizeof(_cmsICCPROFILE));
ContextID = cmsGetProfileContextID(hProfile);
@@ -1294,18 +1354,19 @@
// Pass #1 does compute offsets
- if (!_cmsWriteHeader(Icc, 0)) return 0;
- if (!SaveTags(Icc, &Keep)) return 0;
+ if (!_cmsWriteHeader(Icc, 0)) goto Error;
+ if (!SaveTags(Icc, &Keep)) goto Error;
UsedSpace = PrevIO ->UsedSpace;
// Pass #2 does save to iohandler
if (io != NULL) {
+
Icc ->IOhandler = io;
- if (!SetLinks(Icc)) goto CleanUp;
- if (!_cmsWriteHeader(Icc, UsedSpace)) goto CleanUp;
- if (!SaveTags(Icc, &Keep)) goto CleanUp;
+ if (!SetLinks(Icc)) goto Error;
+ if (!_cmsWriteHeader(Icc, UsedSpace)) goto Error;
+ if (!SaveTags(Icc, &Keep)) goto Error;
}
memmove(Icc, &Keep, sizeof(_cmsICCPROFILE));
@@ -1314,7 +1375,7 @@
return UsedSpace;
-CleanUp:
+Error:
cmsCloseIOhandler(PrevIO);
memmove(Icc, &Keep, sizeof(_cmsICCPROFILE));
return 0;
@@ -1362,11 +1423,13 @@
cmsIOHANDLER* io;
cmsContext ContextID = cmsGetProfileContextID(hProfile);
+ _cmsAssert(BytesNeeded != NULL);
+
// Should we just calculate the needed space?
if (MemPtr == NULL) {
*BytesNeeded = cmsSaveProfileToIOhandler(hProfile, NULL);
- return (*BytesNeeded == 0 ? FALSE : TRUE);
+ return (*BytesNeeded == 0) ? FALSE : TRUE;
}
// That is a real write operation
@@ -1419,6 +1482,8 @@
rc &= cmsCloseIOhandler(Icc->IOhandler);
}
+ _cmsDestroyMutex(Icc->ContextID, Icc->UsrMutex);
+
_cmsFree(Icc ->ContextID, Icc); // Free placeholder memory
return rc;
@@ -1459,14 +1524,18 @@
cmsUInt32Number ElemCount;
int n;
+ if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return NULL;
+
n = _cmsSearchTag(Icc, sig, TRUE);
- if (n < 0) return NULL; // Not found, return NULL
+ if (n < 0) goto Error; // Not found, return NULL
// If the element is already in memory, return the pointer
if (Icc -> TagPtrs[n]) {
- if (Icc ->TagSaveAsRaw[n]) return NULL; // We don't support read raw tags as cooked
+ if (Icc ->TagSaveAsRaw[n]) goto Error; // We don't support read raw tags as cooked
+
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return Icc -> TagPtrs[n];
}
@@ -1476,23 +1545,32 @@
// Seek to its location
if (!io -> Seek(io, Offset))
- return NULL;
+ goto Error;
// Search for support on this tag
- TagDescriptor = _cmsGetTagDescriptor(sig);
- if (TagDescriptor == NULL) return NULL; // Unsupported.
+ TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, sig);
+ if (TagDescriptor == NULL) {
+
+ char String[5];
+
+ _cmsTagSignature2String(String, sig);
+
+ // An unknown element was found.
+ cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown tag type '%s' found.", String);
+ goto Error; // Unsupported.
+ }
// if supported, get type and check if in list
BaseType = _cmsReadTypeBase(io);
- if (BaseType == 0) return NULL;
+ if (BaseType == 0) goto Error;
- if (!IsTypeSupported(TagDescriptor, BaseType)) return NULL;
+ if (!IsTypeSupported(TagDescriptor, BaseType)) goto Error;
TagSize -= 8; // Alredy read by the type base logic
// Get type handler
- TypeHandler = _cmsGetTagTypeHandler(BaseType);
- if (TypeHandler == NULL) return NULL;
+ TypeHandler = _cmsGetTagTypeHandler(Icc ->ContextID, BaseType);
+ if (TypeHandler == NULL) goto Error;
LocalTypeHandler = *TypeHandler;
@@ -1511,7 +1589,7 @@
_cmsTagSignature2String(String, sig);
cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "Corrupted tag '%s'", String);
- return NULL;
+ goto Error;
}
// This is a weird error that may be a symptom of something more serious, the number of
@@ -1527,7 +1605,14 @@
// Return the data
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return Icc -> TagPtrs[n];
+
+
+ // Return error and unlock tha data
+Error:
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
+ return NULL;
}
@@ -1561,49 +1646,26 @@
cmsFloat64Number Version;
char TypeString[5], SigString[5];
+ if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return FALSE;
+ // To delete tags.
if (data == NULL) {
+ // Delete the tag
i = _cmsSearchTag(Icc, sig, FALSE);
- if (i >= 0)
+ if (i >= 0) {
+
+ // Use zero as a mark of deleted
+ _cmsDeleteTagByPos(Icc, i);
Icc ->TagNames[i] = (cmsTagSignature) 0;
- // Unsupported by now, reserved for future ampliations (delete)
- return FALSE;
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
+ return TRUE;
+ }
+ // Didn't find the tag
+ goto Error;
}
- i = _cmsSearchTag(Icc, sig, FALSE);
- if (i >=0) {
-
- if (Icc -> TagPtrs[i] != NULL) {
-
- // Already exists. Free previous version
- if (Icc ->TagSaveAsRaw[i]) {
- _cmsFree(Icc ->ContextID, Icc ->TagPtrs[i]);
- }
- else {
- TypeHandler = Icc ->TagTypeHandlers[i];
-
- if (TypeHandler != NULL) {
-
- LocalTypeHandler = *TypeHandler;
- LocalTypeHandler.ContextID = Icc ->ContextID; // As an additional parameter
- LocalTypeHandler.ICCVersion = Icc ->Version;
- LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc -> TagPtrs[i]);
- }
- }
- }
- }
- else {
- // New one
- i = Icc -> TagCount;
-
- if (i >= MAX_TABLE_TAG) {
- cmsSignalError(Icc ->ContextID, cmsERROR_RANGE, "Too many tags (%d)", MAX_TABLE_TAG);
- return FALSE;
- }
-
- Icc -> TagCount++;
- }
+ if (!_cmsNewTag(Icc, sig, &i)) goto Error;
// This is not raw
Icc ->TagSaveAsRaw[i] = FALSE;
@@ -1612,10 +1674,10 @@
Icc ->TagLinked[i] = (cmsTagSignature) 0;
// Get information about the TAG.
- TagDescriptor = _cmsGetTagDescriptor(sig);
+ TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, sig);
if (TagDescriptor == NULL){
cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported tag '%x'", sig);
- return FALSE;
+ goto Error;
}
@@ -1633,7 +1695,6 @@
}
else {
-
Type = TagDescriptor ->SupportedTypes[0];
}
@@ -1644,18 +1705,18 @@
_cmsTagSignature2String(SigString, sig);
cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported type '%s' for tag '%s'", TypeString, SigString);
- return FALSE;
+ goto Error;
}
// Does we have a handler for this type?
- TypeHandler = _cmsGetTagTypeHandler(Type);
+ TypeHandler = _cmsGetTagTypeHandler(Icc->ContextID, Type);
if (TypeHandler == NULL) {
_cmsTagSignature2String(TypeString, (cmsTagSignature) Type);
_cmsTagSignature2String(SigString, sig);
cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported type '%s' for tag '%s'", TypeString, SigString);
- return FALSE; // Should never happen
+ goto Error; // Should never happen
}
@@ -1668,7 +1729,7 @@
LocalTypeHandler = *TypeHandler;
LocalTypeHandler.ContextID = Icc ->ContextID;
LocalTypeHandler.ICCVersion = Icc ->Version;
- Icc ->TagPtrs[i] = LocalTypeHandler.DupPtr(&LocalTypeHandler, data, TagDescriptor ->ElemCount);
+ Icc ->TagPtrs[i] = LocalTypeHandler.DupPtr(&LocalTypeHandler, data, TagDescriptor ->ElemCount);
if (Icc ->TagPtrs[i] == NULL) {
@@ -1676,10 +1737,16 @@
_cmsTagSignature2String(SigString, sig);
cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "Malformed struct in type '%s' for tag '%s'", TypeString, SigString);
- return FALSE;
+ goto Error;
}
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return TRUE;
+
+Error:
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
+ return FALSE;
+
}
// Read and write raw data. The only way those function would work and keep consistence with normal read and write
@@ -1700,9 +1767,11 @@
cmsUInt32Number rc;
cmsUInt32Number Offset, TagSize;
+ if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return 0;
+
// Search for given tag in ICC profile directory
i = _cmsSearchTag(Icc, sig, TRUE);
- if (i < 0) return 0; // Not found, return 0
+ if (i < 0) goto Error; // Not found,
// It is already read?
if (Icc -> TagPtrs[i] == NULL) {
@@ -1717,12 +1786,14 @@
if (BufferSize < TagSize)
TagSize = BufferSize;
- if (!Icc ->IOhandler ->Seek(Icc ->IOhandler, Offset)) return 0;
- if (!Icc ->IOhandler ->Read(Icc ->IOhandler, data, 1, TagSize)) return 0;
+ if (!Icc ->IOhandler ->Seek(Icc ->IOhandler, Offset)) goto Error;
+ if (!Icc ->IOhandler ->Read(Icc ->IOhandler, data, 1, TagSize)) goto Error;
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return TagSize;
}
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return Icc ->TagSizes[i];
}
@@ -1738,16 +1809,22 @@
memmove(data, Icc ->TagPtrs[i], TagSize);
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return TagSize;
}
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return Icc ->TagSizes[i];
}
// Already readed, or previously set by cmsWriteTag(). We need to serialize that
// data to raw in order to maintain consistency.
+
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
Object = cmsReadTag(hProfile, sig);
- if (Object == NULL) return 0;
+ if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return 0;
+
+ if (Object == NULL) goto Error;
// Now we need to serialize to a memory block: just use a memory iohandler
@@ -1756,17 +1833,18 @@
} else{
MemIO = cmsOpenIOhandlerFromMem(cmsGetProfileContextID(hProfile), data, BufferSize, "w");
}
- if (MemIO == NULL) return 0;
+ if (MemIO == NULL) goto Error;
// Obtain type handling for the tag
TypeHandler = Icc ->TagTypeHandlers[i];
- TagDescriptor = _cmsGetTagDescriptor(sig);
+ TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, sig);
if (TagDescriptor == NULL) {
cmsCloseIOhandler(MemIO);
- return 0;
+ goto Error;
}
- // FIXME: No handling for TypeHandler == NULL here?
+ if (TypeHandler == NULL) goto Error;
+
// Serialize
LocalTypeHandler = *TypeHandler;
LocalTypeHandler.ContextID = Icc ->ContextID;
@@ -1774,19 +1852,24 @@
if (!_cmsWriteTypeBase(MemIO, TypeHandler ->Signature)) {
cmsCloseIOhandler(MemIO);
- return 0;
+ goto Error;
}
if (!LocalTypeHandler.WritePtr(&LocalTypeHandler, MemIO, Object, TagDescriptor ->ElemCount)) {
cmsCloseIOhandler(MemIO);
- return 0;
+ goto Error;
}
// Get Size and close
rc = MemIO ->Tell(MemIO);
cmsCloseIOhandler(MemIO); // Ignore return code this time
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return rc;
+
+Error:
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
+ return 0;
}
// Similar to the anterior. This function allows to write directly to the ICC profile any data, without
@@ -1798,7 +1881,12 @@
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
int i;
- if (!_cmsNewTag(Icc, sig, &i)) return FALSE;
+ if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return 0;
+
+ if (!_cmsNewTag(Icc, sig, &i)) {
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
+ return FALSE;
+ }
// Mark the tag as being written as RAW
Icc ->TagSaveAsRaw[i] = TRUE;
@@ -1809,6 +1897,7 @@
Icc ->TagPtrs[i] = _cmsDupMem(Icc ->ContextID, data, Size);
Icc ->TagSizes[i] = Size;
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return TRUE;
}
@@ -1818,7 +1907,12 @@
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
int i;
- if (!_cmsNewTag(Icc, sig, &i)) return FALSE;
+ if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return FALSE;
+
+ if (!_cmsNewTag(Icc, sig, &i)) {
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
+ return FALSE;
+ }
// Keep necessary information
Icc ->TagSaveAsRaw[i] = FALSE;
@@ -1829,6 +1923,7 @@
Icc ->TagSizes[i] = 0;
Icc ->TagOffsets[i] = 0;
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return TRUE;
}
--- a/jdk/src/java.desktop/share/native/liblcms/cmsio1.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/cmsio1.c Wed Jul 05 20:01:44 2017 +0200
@@ -334,7 +334,8 @@
// Read and create a BRAND NEW MPE LUT from a given profile. All stuff dependent of version, etc
-// is adjusted here in order to create a LUT that takes care of all those details
+// is adjusted here in order to create a LUT that takes care of all those details.
+// We add intent = -1 as a way to read matrix shaper always, no matter of other LUT
cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent)
{
cmsTagTypeSignature OriginalType;
@@ -364,49 +365,54 @@
return Lut;
}
- if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence
+ // This is an attempt to reuse this funtion to retrieve the matrix-shaper as pipeline no
+ // matter other LUT are present and have precedence. Intent = -1 means just this.
+ if (Intent != -1) {
- // Floating point LUT are always V4, but the encoding range is no
- // longer 0..1.0, so we need to add an stage depending on the color space
- return _cmsReadFloatInputTag(hProfile, tagFloat);
- }
+ if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence
+
+ // Floating point LUT are always V4, but the encoding range is no
+ // longer 0..1.0, so we need to add an stage depending on the color space
+ return _cmsReadFloatInputTag(hProfile, tagFloat);
+ }
- // Revert to perceptual if no tag is found
- if (!cmsIsTag(hProfile, tag16)) {
- tag16 = Device2PCS16[0];
- }
+ // Revert to perceptual if no tag is found
+ if (!cmsIsTag(hProfile, tag16)) {
+ tag16 = Device2PCS16[0];
+ }
- if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table?
+ if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table?
- // Check profile version and LUT type. Do the necessary adjustments if needed
+ // Check profile version and LUT type. Do the necessary adjustments if needed
- // First read the tag
- cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16);
- if (Lut == NULL) return NULL;
+ // First read the tag
+ cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16);
+ if (Lut == NULL) return NULL;
- // After reading it, we have now info about the original type
- OriginalType = _cmsGetTagTrueType(hProfile, tag16);
+ // After reading it, we have now info about the original type
+ OriginalType = _cmsGetTagTrueType(hProfile, tag16);
- // The profile owns the Lut, so we need to copy it
- Lut = cmsPipelineDup(Lut);
+ // The profile owns the Lut, so we need to copy it
+ Lut = cmsPipelineDup(Lut);
- // We need to adjust data only for Lab16 on output
- if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData)
- return Lut;
+ // We need to adjust data only for Lab16 on output
+ if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData)
+ return Lut;
- // If the input is Lab, add also a conversion at the begin
- if (cmsGetColorSpace(hProfile) == cmsSigLabData &&
- !cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)))
- goto Error;
+ // If the input is Lab, add also a conversion at the begin
+ if (cmsGetColorSpace(hProfile) == cmsSigLabData &&
+ !cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)))
+ goto Error;
- // Add a matrix for conversion V2 to V4 Lab PCS
- if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
- goto Error;
+ // Add a matrix for conversion V2 to V4 Lab PCS
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
+ goto Error;
- return Lut;
+ return Lut;
Error:
- cmsPipelineFree(Lut);
- return NULL;
+ cmsPipelineFree(Lut);
+ return NULL;
+ }
}
// Lut was not found, try to create a matrix-shaper
@@ -551,7 +557,7 @@
_cmsStageCLutData* CLUT = (_cmsStageCLutData*) Stage ->Data;
CLUT ->Params->dwFlags |= CMS_LERP_FLAGS_TRILINEAR;
- _cmsSetInterpolationRoutine(CLUT ->Params);
+ _cmsSetInterpolationRoutine(Lut->ContextID, CLUT ->Params);
}
}
}
@@ -609,54 +615,58 @@
cmsTagSignature tagFloat = PCS2DeviceFloat[Intent];
cmsContext ContextID = cmsGetProfileContextID(hProfile);
- if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence
+
+ if (Intent != -1) {
- // Floating point LUT are always V4
- return _cmsReadFloatOutputTag(hProfile, tagFloat);
- }
+ if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence
+
+ // Floating point LUT are always V4
+ return _cmsReadFloatOutputTag(hProfile, tagFloat);
+ }
- // Revert to perceptual if no tag is found
- if (!cmsIsTag(hProfile, tag16)) {
- tag16 = PCS2Device16[0];
- }
+ // Revert to perceptual if no tag is found
+ if (!cmsIsTag(hProfile, tag16)) {
+ tag16 = PCS2Device16[0];
+ }
- if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table?
-
- // Check profile version and LUT type. Do the necessary adjustments if needed
+ if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table?
- // First read the tag
- cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16);
- if (Lut == NULL) return NULL;
+ // Check profile version and LUT type. Do the necessary adjustments if needed
- // After reading it, we have info about the original type
- OriginalType = _cmsGetTagTrueType(hProfile, tag16);
+ // First read the tag
+ cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16);
+ if (Lut == NULL) return NULL;
- // The profile owns the Lut, so we need to copy it
- Lut = cmsPipelineDup(Lut);
- if (Lut == NULL) return NULL;
+ // After reading it, we have info about the original type
+ OriginalType = _cmsGetTagTrueType(hProfile, tag16);
- // Now it is time for a controversial stuff. I found that for 3D LUTS using
- // Lab used as indexer space, trilinear interpolation should be used
- if (cmsGetPCS(hProfile) == cmsSigLabData)
- ChangeInterpolationToTrilinear(Lut);
+ // The profile owns the Lut, so we need to copy it
+ Lut = cmsPipelineDup(Lut);
+ if (Lut == NULL) return NULL;
- // We need to adjust data only for Lab and Lut16 type
- if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData)
- return Lut;
+ // Now it is time for a controversial stuff. I found that for 3D LUTS using
+ // Lab used as indexer space, trilinear interpolation should be used
+ if (cmsGetPCS(hProfile) == cmsSigLabData)
+ ChangeInterpolationToTrilinear(Lut);
- // Add a matrix for conversion V4 to V2 Lab PCS
- if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)))
- goto Error;
+ // We need to adjust data only for Lab and Lut16 type
+ if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData)
+ return Lut;
- // If the output is Lab, add also a conversion at the end
- if (cmsGetColorSpace(hProfile) == cmsSigLabData)
- if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
+ // Add a matrix for conversion V4 to V2 Lab PCS
+ if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)))
goto Error;
- return Lut;
+ // If the output is Lab, add also a conversion at the end
+ if (cmsGetColorSpace(hProfile) == cmsSigLabData)
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
+ goto Error;
+
+ return Lut;
Error:
- cmsPipelineFree(Lut);
- return NULL;
+ cmsPipelineFree(Lut);
+ return NULL;
+ }
}
// Lut not found, try to create a matrix-shaper
@@ -782,7 +792,7 @@
// Now it is time for a controversial stuff. I found that for 3D LUTS using
// Lab used as indexer space, trilinear interpolation should be used
- if (cmsGetColorSpace(hProfile) == cmsSigLabData)
+ if (cmsGetPCS(hProfile) == cmsSigLabData)
ChangeInterpolationToTrilinear(Lut);
// After reading it, we have info about the original type
@@ -793,12 +803,12 @@
// Here it is possible to get Lab on both sides
- if (cmsGetPCS(hProfile) == cmsSigLabData) {
+ if (cmsGetColorSpace(hProfile) == cmsSigLabData) {
if(!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)))
goto Error2;
}
- if (cmsGetColorSpace(hProfile) == cmsSigLabData) {
+ if (cmsGetPCS(hProfile) == cmsSigLabData) {
if(!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
goto Error2;
}
--- a/jdk/src/java.desktop/share/native/liblcms/cmsopt.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/cmsopt.c Wed Jul 05 20:01:44 2017 +0200
@@ -542,11 +542,13 @@
cmsToneCurve* InversePostLin = cmsReverseToneCurve(Curves[i]);
if (InversePostLin == NULL) {
- WhiteOut[i] = 0;
- continue;
+ WhiteOut[i] = WhitePointOut[i];
+
+ } else {
+
+ WhiteOut[i] = cmsEvalToneCurve16(InversePostLin, WhitePointOut[i]);
+ cmsFreeToneCurve(InversePostLin);
}
- WhiteOut[i] = cmsEvalToneCurve16(InversePostLin, WhitePointOut[i]);
- cmsFreeToneCurve(InversePostLin);
}
}
else {
@@ -1666,44 +1668,102 @@
};
// The linked list head
-static _cmsOptimizationCollection* OptimizationCollection = DefaultOptimization;
+_cmsOptimizationPluginChunkType _cmsOptimizationPluginChunk = { NULL };
+
+
+// Duplicates the zone of memory used by the plug-in in the new context
+static
+void DupPluginOptimizationList(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ _cmsOptimizationPluginChunkType newHead = { NULL };
+ _cmsOptimizationCollection* entry;
+ _cmsOptimizationCollection* Anterior = NULL;
+ _cmsOptimizationPluginChunkType* head = (_cmsOptimizationPluginChunkType*) src->chunks[OptimizationPlugin];
+
+ _cmsAssert(ctx != NULL);
+ _cmsAssert(head != NULL);
+
+ // Walk the list copying all nodes
+ for (entry = head->OptimizationCollection;
+ entry != NULL;
+ entry = entry ->Next) {
+
+ _cmsOptimizationCollection *newEntry = ( _cmsOptimizationCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsOptimizationCollection));
+
+ if (newEntry == NULL)
+ return;
+
+ // We want to keep the linked list order, so this is a little bit tricky
+ newEntry -> Next = NULL;
+ if (Anterior)
+ Anterior -> Next = newEntry;
+
+ Anterior = newEntry;
+
+ if (newHead.OptimizationCollection == NULL)
+ newHead.OptimizationCollection = newEntry;
+ }
+
+ ctx ->chunks[OptimizationPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsOptimizationPluginChunkType));
+}
+
+void _cmsAllocOptimizationPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ if (src != NULL) {
+
+ // Copy all linked list
+ DupPluginOptimizationList(ctx, src);
+ }
+ else {
+ static _cmsOptimizationPluginChunkType OptimizationPluginChunkType = { NULL };
+ ctx ->chunks[OptimizationPlugin] = _cmsSubAllocDup(ctx ->MemPool, &OptimizationPluginChunkType, sizeof(_cmsOptimizationPluginChunkType));
+ }
+}
+
// Register new ways to optimize
-cmsBool _cmsRegisterOptimizationPlugin(cmsContext id, cmsPluginBase* Data)
+cmsBool _cmsRegisterOptimizationPlugin(cmsContext ContextID, cmsPluginBase* Data)
{
cmsPluginOptimization* Plugin = (cmsPluginOptimization*) Data;
+ _cmsOptimizationPluginChunkType* ctx = ( _cmsOptimizationPluginChunkType*) _cmsContextGetClientChunk(ContextID, OptimizationPlugin);
_cmsOptimizationCollection* fl;
if (Data == NULL) {
- OptimizationCollection = DefaultOptimization;
+ ctx->OptimizationCollection = NULL;
return TRUE;
}
// Optimizer callback is required
if (Plugin ->OptimizePtr == NULL) return FALSE;
- fl = (_cmsOptimizationCollection*) _cmsPluginMalloc(id, sizeof(_cmsOptimizationCollection));
+ fl = (_cmsOptimizationCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsOptimizationCollection));
if (fl == NULL) return FALSE;
// Copy the parameters
fl ->OptimizePtr = Plugin ->OptimizePtr;
// Keep linked list
- fl ->Next = OptimizationCollection;
- OptimizationCollection = fl;
+ fl ->Next = ctx->OptimizationCollection;
+
+ // Set the head
+ ctx ->OptimizationCollection = fl;
// All is ok
return TRUE;
}
// The entry point for LUT optimization
-cmsBool _cmsOptimizePipeline(cmsPipeline** PtrLut,
+cmsBool _cmsOptimizePipeline(cmsContext ContextID,
+ cmsPipeline** PtrLut,
int Intent,
cmsUInt32Number* InputFormat,
cmsUInt32Number* OutputFormat,
cmsUInt32Number* dwFlags)
{
+ _cmsOptimizationPluginChunkType* ctx = ( _cmsOptimizationPluginChunkType*) _cmsContextGetClientChunk(ContextID, OptimizationPlugin);
_cmsOptimizationCollection* Opts;
cmsBool AnySuccess = FALSE;
@@ -1733,8 +1793,8 @@
if (*dwFlags & cmsFLAGS_NOOPTIMIZE)
return FALSE;
- // Try built-in optimizations and plug-in
- for (Opts = OptimizationCollection;
+ // Try plug-in optimizations
+ for (Opts = ctx->OptimizationCollection;
Opts != NULL;
Opts = Opts ->Next) {
@@ -1745,6 +1805,17 @@
}
}
+ // Try built-in optimizations
+ for (Opts = DefaultOptimization;
+ Opts != NULL;
+ Opts = Opts ->Next) {
+
+ if (Opts ->OptimizePtr(PtrLut, Intent, InputFormat, OutputFormat, dwFlags)) {
+
+ return TRUE;
+ }
+ }
+
// Only simple optimizations succeeded
return AnySuccess;
}
--- a/jdk/src/java.desktop/share/native/liblcms/cmspack.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/cmspack.c Wed Jul 05 20:01:44 2017 +0200
@@ -883,6 +883,42 @@
}
}
+// This is a conversion of XYZ float to 16 bits
+static
+cmsUInt8Number* UnrollXYZFloatTo16(register _cmsTRANSFORM* info,
+ register cmsUInt16Number wIn[],
+ register cmsUInt8Number* accum,
+ register cmsUInt32Number Stride)
+{
+ if (T_PLANAR(info -> InputFormat)) {
+
+ cmsFloat32Number* Pt = (cmsFloat32Number*) accum;
+ cmsCIEXYZ XYZ;
+
+ XYZ.X = Pt[0];
+ XYZ.Y = Pt[Stride];
+ XYZ.Z = Pt[Stride*2];
+ cmsFloat2XYZEncoded(wIn, &XYZ);
+
+ return accum + sizeof(cmsFloat32Number);
+
+ }
+
+ else {
+ cmsFloat32Number* Pt = (cmsFloat32Number*) accum;
+ cmsCIEXYZ XYZ;
+
+ XYZ.X = Pt[0];
+ XYZ.Y = Pt[1];
+ XYZ.Z = Pt[2];
+ cmsFloat2XYZEncoded(wIn, &XYZ);
+
+ accum += 3 * sizeof(cmsFloat32Number) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat32Number);
+
+ return accum;
+ }
+}
+
// Check if space is marked as ink
cmsINLINE cmsBool IsInkSpace(cmsUInt32Number Type)
{
@@ -2334,6 +2370,39 @@
}
static
+cmsUInt8Number* PackXYZFloatFrom16(register _cmsTRANSFORM* Info,
+ register cmsUInt16Number wOut[],
+ register cmsUInt8Number* output,
+ register cmsUInt32Number Stride)
+{
+ if (T_PLANAR(Info -> OutputFormat)) {
+
+ cmsCIEXYZ XYZ;
+ cmsFloat32Number* Out = (cmsFloat32Number*) output;
+ cmsXYZEncoded2Float(&XYZ, wOut);
+
+ Out[0] = (cmsFloat32Number) XYZ.X;
+ Out[Stride] = (cmsFloat32Number) XYZ.Y;
+ Out[Stride*2] = (cmsFloat32Number) XYZ.Z;
+
+ return output + sizeof(cmsFloat32Number);
+
+ }
+ else {
+
+ cmsCIEXYZ XYZ;
+ cmsFloat32Number* Out = (cmsFloat32Number*) output;
+ cmsXYZEncoded2Float(&XYZ, wOut);
+
+ Out[0] = (cmsFloat32Number) XYZ.X;
+ Out[1] = (cmsFloat32Number) XYZ.Y;
+ Out[2] = (cmsFloat32Number) XYZ.Z;
+
+ return output + (3 * sizeof(cmsFloat32Number) + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number));
+ }
+}
+
+static
cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* info,
register cmsUInt16Number wOut[],
register cmsUInt8Number* output,
@@ -2893,6 +2962,7 @@
{ TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, UnrollLabDoubleTo16},
{ TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, UnrollXYZDoubleTo16},
{ TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, UnrollLabFloatTo16},
+ { TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, UnrollXYZFloatTo16},
{ TYPE_GRAY_DBL, 0, UnrollDouble1Chan},
{ FLOAT_SH(1)|BYTES_SH(0), ANYCHANNELS|ANYPLANAR|ANYSWAPFIRST|ANYFLAVOR|
ANYSWAP|ANYEXTRA|ANYSPACE, UnrollDoubleTo16},
@@ -3027,6 +3097,7 @@
{ TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, PackXYZDoubleFrom16},
{ TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, PackLabFloatFrom16},
+ { TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, PackXYZFloatFrom16},
{ FLOAT_SH(1)|BYTES_SH(0), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|
ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE, PackDoubleFrom16},
@@ -3182,40 +3253,98 @@
} cmsFormattersFactoryList;
-static cmsFormattersFactoryList* FactoryList = NULL;
+_cmsFormattersPluginChunkType _cmsFormattersPluginChunk = { NULL };
+
+
+// Duplicates the zone of memory used by the plug-in in the new context
+static
+void DupFormatterFactoryList(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ _cmsFormattersPluginChunkType newHead = { NULL };
+ cmsFormattersFactoryList* entry;
+ cmsFormattersFactoryList* Anterior = NULL;
+ _cmsFormattersPluginChunkType* head = (_cmsFormattersPluginChunkType*) src->chunks[FormattersPlugin];
+
+ _cmsAssert(head != NULL);
+
+ // Walk the list copying all nodes
+ for (entry = head->FactoryList;
+ entry != NULL;
+ entry = entry ->Next) {
+
+ cmsFormattersFactoryList *newEntry = ( cmsFormattersFactoryList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(cmsFormattersFactoryList));
+
+ if (newEntry == NULL)
+ return;
+
+ // We want to keep the linked list order, so this is a little bit tricky
+ newEntry -> Next = NULL;
+ if (Anterior)
+ Anterior -> Next = newEntry;
+
+ Anterior = newEntry;
+
+ if (newHead.FactoryList == NULL)
+ newHead.FactoryList = newEntry;
+ }
+
+ ctx ->chunks[FormattersPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsFormattersPluginChunkType));
+}
+
+// The interpolation plug-in memory chunk allocator/dup
+void _cmsAllocFormattersPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ _cmsAssert(ctx != NULL);
+
+ if (src != NULL) {
+
+ // Duplicate the LIST
+ DupFormatterFactoryList(ctx, src);
+ }
+ else {
+ static _cmsFormattersPluginChunkType FormattersPluginChunk = { NULL };
+ ctx ->chunks[FormattersPlugin] = _cmsSubAllocDup(ctx ->MemPool, &FormattersPluginChunk, sizeof(_cmsFormattersPluginChunkType));
+ }
+}
+
// Formatters management
-cmsBool _cmsRegisterFormattersPlugin(cmsContext id, cmsPluginBase* Data)
+cmsBool _cmsRegisterFormattersPlugin(cmsContext ContextID, cmsPluginBase* Data)
{
+ _cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin);
cmsPluginFormatters* Plugin = (cmsPluginFormatters*) Data;
cmsFormattersFactoryList* fl ;
- // Reset
+ // Reset to built-in defaults
if (Data == NULL) {
- FactoryList = NULL;
+ ctx ->FactoryList = NULL;
return TRUE;
}
- fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(id, sizeof(cmsFormattersFactoryList));
+ fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(ContextID, sizeof(cmsFormattersFactoryList));
if (fl == NULL) return FALSE;
fl ->Factory = Plugin ->FormattersFactory;
- fl ->Next = FactoryList;
- FactoryList = fl;
+ fl ->Next = ctx -> FactoryList;
+ ctx ->FactoryList = fl;
return TRUE;
}
-cmsFormatter _cmsGetFormatter(cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8
+cmsFormatter _cmsGetFormatter(cmsContext ContextID,
+ cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8
cmsFormatterDirection Dir,
cmsUInt32Number dwFlags)
{
+ _cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin);
cmsFormattersFactoryList* f;
- for (f = FactoryList; f != NULL; f = f ->Next) {
+ for (f =ctx->FactoryList; f != NULL; f = f ->Next) {
cmsFormatter fn = f ->Factory(Type, Dir, dwFlags);
if (fn.Fmt16 != NULL) return fn;
--- a/jdk/src/java.desktop/share/native/liblcms/cmsplugin.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/cmsplugin.c Wed Jul 05 20:01:44 2017 +0200
@@ -544,22 +544,31 @@
// Plugin memory management -------------------------------------------------------------------------------------------------
-static _cmsSubAllocator* PluginPool = NULL;
-
// Specialized malloc for plug-ins, that is freed upon exit.
-void* _cmsPluginMalloc(cmsContext id, cmsUInt32Number size)
+void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size)
{
- if (PluginPool == NULL)
- PluginPool = _cmsCreateSubAlloc(id, 4*1024);
+ struct _cmsContext_struct* ctx = _cmsGetContext(ContextID);
+
+ if (ctx ->MemPool == NULL) {
+
+ if (ContextID == NULL) {
- return _cmsSubAlloc(PluginPool, size);
+ ctx->MemPool = _cmsCreateSubAlloc(0, 2*1024);
+ }
+ else {
+ cmsSignalError(ContextID, cmsERROR_CORRUPTION_DETECTED, "NULL memory pool on context");
+ return NULL;
+ }
+ }
+
+ return _cmsSubAlloc(ctx->MemPool, size);
}
// Main plug-in dispatcher
cmsBool CMSEXPORT cmsPlugin(void* Plug_in)
{
- return cmsPluginTHR(NULL, Plug_in);
+ return cmsPluginTHR(NULL, Plug_in);
}
cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in)
@@ -571,12 +580,12 @@
Plugin = Plugin -> Next) {
if (Plugin -> Magic != cmsPluginMagicNumber) {
- cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin");
+ cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin");
return FALSE;
}
if (Plugin ->ExpectedVersion > LCMS_VERSION) {
- cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "plugin needs Little CMS %d, current version is %d",
+ cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "plugin needs Little CMS %d, current version is %d",
Plugin ->ExpectedVersion, LCMS_VERSION);
return FALSE;
}
@@ -584,11 +593,11 @@
switch (Plugin -> Type) {
case cmsPluginMemHandlerSig:
- if (!_cmsRegisterMemHandlerPlugin(Plugin)) return FALSE;
+ if (!_cmsRegisterMemHandlerPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginInterpolationSig:
- if (!_cmsRegisterInterpPlugin(Plugin)) return FALSE;
+ if (!_cmsRegisterInterpPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginTagTypeSig:
@@ -623,8 +632,12 @@
if (!_cmsRegisterTransformPlugin(id, Plugin)) return FALSE;
break;
+ case cmsPluginMutexSig:
+ if (!_cmsRegisterMutexPlugin(id, Plugin)) return FALSE;
+ break;
+
default:
- cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin type '%X'", Plugin -> Type);
+ cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin type '%X'", Plugin -> Type);
return FALSE;
}
}
@@ -637,19 +650,337 @@
// Revert all plug-ins to default
void CMSEXPORT cmsUnregisterPlugins(void)
{
- _cmsRegisterMemHandlerPlugin(NULL);
- _cmsRegisterInterpPlugin(NULL);
- _cmsRegisterTagTypePlugin(NULL, NULL);
- _cmsRegisterTagPlugin(NULL, NULL);
- _cmsRegisterFormattersPlugin(NULL, NULL);
- _cmsRegisterRenderingIntentPlugin(NULL, NULL);
- _cmsRegisterParametricCurvesPlugin(NULL, NULL);
- _cmsRegisterMultiProcessElementPlugin(NULL, NULL);
- _cmsRegisterOptimizationPlugin(NULL, NULL);
- _cmsRegisterTransformPlugin(NULL, NULL);
+ cmsUnregisterPluginsTHR(NULL);
+}
+
+
+// The Global storage for system context. This is the one and only global variable
+// pointers structure. All global vars are referenced here.
+static struct _cmsContext_struct globalContext = {
+
+ NULL, // Not in the linked list
+ NULL, // No suballocator
+ {
+ NULL, // UserPtr,
+ &_cmsLogErrorChunk, // Logger,
+ &_cmsAlarmCodesChunk, // AlarmCodes,
+ &_cmsAdaptationStateChunk, // AdaptationState,
+ &_cmsMemPluginChunk, // MemPlugin,
+ &_cmsInterpPluginChunk, // InterpPlugin,
+ &_cmsCurvesPluginChunk, // CurvesPlugin,
+ &_cmsFormattersPluginChunk, // FormattersPlugin,
+ &_cmsTagTypePluginChunk, // TagTypePlugin,
+ &_cmsTagPluginChunk, // TagPlugin,
+ &_cmsIntentsPluginChunk, // IntentPlugin,
+ &_cmsMPETypePluginChunk, // MPEPlugin,
+ &_cmsOptimizationPluginChunk, // OptimizationPlugin,
+ &_cmsTransformPluginChunk, // TransformPlugin,
+ &_cmsMutexPluginChunk // MutexPlugin
+ },
+
+ { NULL, NULL, NULL, NULL, NULL, NULL } // The default memory allocator is not used for context 0
+};
+
+
+// The context pool (linked list head)
+static _cmsMutex _cmsContextPoolHeadMutex = CMS_MUTEX_INITIALIZER;
+static struct _cmsContext_struct* _cmsContextPoolHead = NULL;
+
+// Internal, get associated pointer, with guessing. Never returns NULL.
+struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID)
+{
+ struct _cmsContext_struct* id = (struct _cmsContext_struct*) ContextID;
+ struct _cmsContext_struct* ctx;
+
+
+ // On 0, use global settings
+ if (id == NULL)
+ return &globalContext;
+
+ // Search
+ for (ctx = _cmsContextPoolHead;
+ ctx != NULL;
+ ctx = ctx ->Next) {
+
+ // Found it?
+ if (id == ctx)
+ return ctx; // New-style context,
+ }
+
+ return &globalContext;
+}
+
+
+// Internal: get the memory area associanted with each context client
+// Returns the block assigned to the specific zone.
+void* _cmsContextGetClientChunk(cmsContext ContextID, _cmsMemoryClient mc)
+{
+ struct _cmsContext_struct* ctx;
+ void *ptr;
+
+ if (mc < 0 || mc >= MemoryClientMax) {
+ cmsSignalError(ContextID, cmsERROR_RANGE, "Bad context client");
+ return NULL;
+ }
+
+ ctx = _cmsGetContext(ContextID);
+ ptr = ctx ->chunks[mc];
+
+ if (ptr != NULL)
+ return ptr;
+
+ // A null ptr means no special settings for that context, and this
+ // reverts to Context0 globals
+ return globalContext.chunks[mc];
+}
+
+
+// This function returns the given context its default pristine state,
+// as no plug-ins were declared. There is no way to unregister a single
+// plug-in, as a single call to cmsPluginTHR() function may register
+// many different plug-ins simultaneously, then there is no way to
+// identify which plug-in to unregister.
+void CMSEXPORT cmsUnregisterPluginsTHR(cmsContext ContextID)
+{
+ _cmsRegisterMemHandlerPlugin(ContextID, NULL);
+ _cmsRegisterInterpPlugin(ContextID, NULL);
+ _cmsRegisterTagTypePlugin(ContextID, NULL);
+ _cmsRegisterTagPlugin(ContextID, NULL);
+ _cmsRegisterFormattersPlugin(ContextID, NULL);
+ _cmsRegisterRenderingIntentPlugin(ContextID, NULL);
+ _cmsRegisterParametricCurvesPlugin(ContextID, NULL);
+ _cmsRegisterMultiProcessElementPlugin(ContextID, NULL);
+ _cmsRegisterOptimizationPlugin(ContextID, NULL);
+ _cmsRegisterTransformPlugin(ContextID, NULL);
+ _cmsRegisterMutexPlugin(ContextID, NULL);
+}
+
+
+// Returns the memory manager plug-in, if any, from the Plug-in bundle
+static
+cmsPluginMemHandler* _cmsFindMemoryPlugin(void* PluginBundle)
+{
+ cmsPluginBase* Plugin;
+
+ for (Plugin = (cmsPluginBase*) PluginBundle;
+ Plugin != NULL;
+ Plugin = Plugin -> Next) {
+
+ if (Plugin -> Magic == cmsPluginMagicNumber &&
+ Plugin -> ExpectedVersion <= LCMS_VERSION &&
+ Plugin -> Type == cmsPluginMemHandlerSig) {
+
+ // Found!
+ return (cmsPluginMemHandler*) Plugin;
+ }
+ }
+
+ // Nope, revert to defaults
+ return NULL;
+}
+
+
+// Creates a new context with optional associated plug-ins. Caller may also specify an optional pointer to user-defined
+// data that will be forwarded to plug-ins and logger.
+cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData)
+{
+ struct _cmsContext_struct* ctx;
+ struct _cmsContext_struct fakeContext;
+
+ _cmsInstallAllocFunctions(_cmsFindMemoryPlugin(Plugin), &fakeContext.DefaultMemoryManager);
+
+ fakeContext.chunks[UserPtr] = UserData;
+ fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager;
+
+ // Create the context structure.
+ ctx = (struct _cmsContext_struct*) _cmsMalloc(&fakeContext, sizeof(struct _cmsContext_struct));
+ if (ctx == NULL)
+ return NULL; // Something very wrong happened!
+
+ // Init the structure and the memory manager
+ memset(ctx, 0, sizeof(struct _cmsContext_struct));
+
+ // Keep memory manager
+ memcpy(&ctx->DefaultMemoryManager, &fakeContext.DefaultMemoryManager, sizeof(_cmsMemPluginChunk));
+
+ // Maintain the linked list (with proper locking)
+ _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
+ ctx ->Next = _cmsContextPoolHead;
+ _cmsContextPoolHead = ctx;
+ _cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
+
+ ctx ->chunks[UserPtr] = UserData;
+ ctx ->chunks[MemPlugin] = &ctx->DefaultMemoryManager;
+
+ // Now we can allocate the pool by using default memory manager
+ ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*)); // default size about 32 pointers
+ if (ctx ->MemPool == NULL) {
- if (PluginPool != NULL)
- _cmsSubAllocDestroy(PluginPool);
+ cmsDeleteContext(ctx);
+ return NULL;
+ }
+
+ _cmsAllocLogErrorChunk(ctx, NULL);
+ _cmsAllocAlarmCodesChunk(ctx, NULL);
+ _cmsAllocAdaptationStateChunk(ctx, NULL);
+ _cmsAllocMemPluginChunk(ctx, NULL);
+ _cmsAllocInterpPluginChunk(ctx, NULL);
+ _cmsAllocCurvesPluginChunk(ctx, NULL);
+ _cmsAllocFormattersPluginChunk(ctx, NULL);
+ _cmsAllocTagTypePluginChunk(ctx, NULL);
+ _cmsAllocMPETypePluginChunk(ctx, NULL);
+ _cmsAllocTagPluginChunk(ctx, NULL);
+ _cmsAllocIntentsPluginChunk(ctx, NULL);
+ _cmsAllocOptimizationPluginChunk(ctx, NULL);
+ _cmsAllocTransformPluginChunk(ctx, NULL);
+ _cmsAllocMutexPluginChunk(ctx, NULL);
+
+ // Setup the plug-ins
+ if (!cmsPluginTHR(ctx, Plugin)) {
+
+ cmsDeleteContext(ctx);
+ return NULL;
+ }
+
+ return (cmsContext) ctx;
+}
+
+// Duplicates a context with all associated plug-ins.
+// Caller may specify an optional pointer to user-defined
+// data that will be forwarded to plug-ins and logger.
+cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData)
+{
+ int i;
+ struct _cmsContext_struct* ctx;
+ const struct _cmsContext_struct* src = _cmsGetContext(ContextID);
+
+ void* userData = (NewUserData != NULL) ? NewUserData : src -> chunks[UserPtr];
+
+
+ ctx = (struct _cmsContext_struct*) _cmsMalloc(ContextID, sizeof(struct _cmsContext_struct));
+ if (ctx == NULL)
+ return NULL; // Something very wrong happened
+
+ // Setup default memory allocators
+ memcpy(&ctx->DefaultMemoryManager, &src->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));
+
+ // Maintain the linked list
+ _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
+ ctx ->Next = _cmsContextPoolHead;
+ _cmsContextPoolHead = ctx;
+ _cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
+
+ ctx ->chunks[UserPtr] = userData;
+ ctx ->chunks[MemPlugin] = &ctx->DefaultMemoryManager;
+
+ ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*));
+ if (ctx ->MemPool == NULL) {
+
+ cmsDeleteContext(ctx);
+ return NULL;
+ }
+
+ // Allocate all required chunks.
+ _cmsAllocLogErrorChunk(ctx, src);
+ _cmsAllocAlarmCodesChunk(ctx, src);
+ _cmsAllocAdaptationStateChunk(ctx, src);
+ _cmsAllocMemPluginChunk(ctx, src);
+ _cmsAllocInterpPluginChunk(ctx, src);
+ _cmsAllocCurvesPluginChunk(ctx, src);
+ _cmsAllocFormattersPluginChunk(ctx, src);
+ _cmsAllocTagTypePluginChunk(ctx, src);
+ _cmsAllocMPETypePluginChunk(ctx, src);
+ _cmsAllocTagPluginChunk(ctx, src);
+ _cmsAllocIntentsPluginChunk(ctx, src);
+ _cmsAllocOptimizationPluginChunk(ctx, src);
+ _cmsAllocTransformPluginChunk(ctx, src);
+ _cmsAllocMutexPluginChunk(ctx, src);
+
+ // Make sure no one failed
+ for (i=Logger; i < MemoryClientMax; i++) {
- PluginPool = NULL;
+ if (src ->chunks[i] == NULL) {
+ cmsDeleteContext((cmsContext) ctx);
+ return NULL;
+ }
+ }
+
+ return (cmsContext) ctx;
+}
+
+
+
+static
+struct _cmsContext_struct* FindPrev(struct _cmsContext_struct* id)
+{
+ struct _cmsContext_struct* prev;
+
+ // Search for previous
+ for (prev = _cmsContextPoolHead;
+ prev != NULL;
+ prev = prev ->Next)
+ {
+ if (prev ->Next == id)
+ return prev;
+ }
+
+ return NULL; // List is empty or only one element!
}
+
+// Frees any resources associated with the given context,
+// and destroys the context placeholder.
+// The ContextID can no longer be used in any THR operation.
+void CMSEXPORT cmsDeleteContext(cmsContext ContextID)
+{
+ if (ContextID != NULL) {
+
+ struct _cmsContext_struct* ctx = (struct _cmsContext_struct*) ContextID;
+ struct _cmsContext_struct fakeContext;
+ struct _cmsContext_struct* prev;
+
+ memcpy(&fakeContext.DefaultMemoryManager, &ctx->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));
+
+ fakeContext.chunks[UserPtr] = ctx ->chunks[UserPtr];
+ fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager;
+
+ // Get rid of plugins
+ cmsUnregisterPluginsTHR(ContextID);
+
+ // Since all memory is allocated in the private pool, all what we need to do is destroy the pool
+ if (ctx -> MemPool != NULL)
+ _cmsSubAllocDestroy(ctx ->MemPool);
+ ctx -> MemPool = NULL;
+
+ // Maintain list
+ _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
+ if (_cmsContextPoolHead == ctx) {
+
+ _cmsContextPoolHead = ctx->Next;
+ }
+ else {
+
+ // Search for previous
+ for (prev = _cmsContextPoolHead;
+ prev != NULL;
+ prev = prev ->Next)
+ {
+ if (prev -> Next == ctx) {
+ prev -> Next = ctx ->Next;
+ break;
+ }
+ }
+ }
+ _cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
+
+ // free the memory block itself
+ _cmsFree(&fakeContext, ctx);
+ }
+}
+
+// Returns the user data associated to the given ContextID, or NULL if no user data was attached on context creation
+void* CMSEXPORT cmsGetContextUserData(cmsContext ContextID)
+{
+ return _cmsContextGetClientChunk(ContextID, UserPtr);
+}
+
+
--- a/jdk/src/java.desktop/share/native/liblcms/cmsps2.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/cmsps2.c Wed Jul 05 20:01:44 2017 +0200
@@ -942,7 +942,7 @@
if (DeviceLink == NULL) return 0;
dwFlags |= cmsFLAGS_FORCE_CLUT;
- _cmsOptimizePipeline(&DeviceLink, Intent, &InputFormat, &OutFrm, &dwFlags);
+ _cmsOptimizePipeline(m->ContextID, &DeviceLink, Intent, &InputFormat, &OutFrm, &dwFlags);
rc = EmitCIEBasedDEF(m, DeviceLink, Intent, &BlackPointAdaptedToD50);
cmsPipelineFree(DeviceLink);
@@ -1359,7 +1359,7 @@
// We need a CLUT
dwFlags |= cmsFLAGS_FORCE_CLUT;
- _cmsOptimizePipeline(&DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags);
+ _cmsOptimizePipeline(m->ContextID, &DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags);
_cmsIOPrintf(m, "<<\n");
_cmsIOPrintf(m, "/ColorRenderingType 1\n");
--- a/jdk/src/java.desktop/share/native/liblcms/cmstypes.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/cmstypes.c Wed Jul 05 20:01:44 2017 +0200
@@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
-// Copyright (c) 1998-2011 Marti Maria Saguer
+// Copyright (c) 1998-2014 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@@ -61,7 +61,7 @@
// are no profiles holding them. The programmer can also extend this list by defining his own types
// by using the appropiate plug-in. There are three types of plug ins regarding that. First type
// allows to define new tags using any existing type. Next plug-in type allows to define new types
-// and the third one is very specific: allows to extend the number of elements in the multiprofile
+// and the third one is very specific: allows to extend the number of elements in the multiprocessing
// elements special type.
//--------------------------------------------------------------------------------------------------
@@ -89,54 +89,49 @@
// Helper macro to define a MPE handler. Callbacks do have a fixed naming convention
#define TYPE_MPE_HANDLER(t, x) { (t), READ_FN(x), WRITE_FN(x), GenericMPEdup, GenericMPEfree, NULL, 0 }
-// Register a new type handler. This routine is shared between normal types and MPE
+// Register a new type handler. This routine is shared between normal types and MPE. LinkedList points to the optional list head
static
-cmsBool RegisterTypesPlugin(cmsContext id, cmsPluginBase* Data, _cmsTagTypeLinkedList* LinkedList, cmsUInt32Number DefaultListCount)
+cmsBool RegisterTypesPlugin(cmsContext id, cmsPluginBase* Data, _cmsMemoryClient pos)
{
cmsPluginTagType* Plugin = (cmsPluginTagType*) Data;
- _cmsTagTypeLinkedList *pt, *Anterior = NULL;
+ _cmsTagTypePluginChunkType* ctx = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(id, pos);
+ _cmsTagTypeLinkedList *pt;
// Calling the function with NULL as plug-in would unregister the plug in.
if (Data == NULL) {
- LinkedList[DefaultListCount-1].Next = NULL;
+ // There is no need to set free the memory, as pool is destroyed as a whole.
+ ctx ->TagTypes = NULL;
return TRUE;
}
- pt = Anterior = LinkedList;
- while (pt != NULL) {
-
- if (Plugin->Handler.Signature == pt -> Handler.Signature) {
- pt ->Handler = Plugin ->Handler; // Replace old behaviour.
- // Note that since no memory is allocated, unregister does not
- // reset this action.
- return TRUE;
- }
-
- Anterior = pt;
- pt = pt ->Next;
- }
-
- // Registering happens in plug-in memory pool
+ // Registering happens in plug-in memory pool.
pt = (_cmsTagTypeLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagTypeLinkedList));
if (pt == NULL) return FALSE;
pt ->Handler = Plugin ->Handler;
- pt ->Next = NULL;
-
- if (Anterior)
- Anterior -> Next = pt;
+ pt ->Next = ctx ->TagTypes;
+
+ ctx ->TagTypes = pt;
return TRUE;
}
-// Return handler for a given type or NULL if not found. Shared between normal types and MPE
+// Return handler for a given type or NULL if not found. Shared between normal types and MPE. It first tries the additons
+// made by plug-ins and then the built-in defaults.
static
-cmsTagTypeHandler* GetHandler(cmsTagTypeSignature sig, _cmsTagTypeLinkedList* LinkedList)
+cmsTagTypeHandler* GetHandler(cmsTagTypeSignature sig, _cmsTagTypeLinkedList* PluginLinkedList, _cmsTagTypeLinkedList* DefaultLinkedList)
{
_cmsTagTypeLinkedList* pt;
- for (pt = LinkedList;
+ for (pt = PluginLinkedList;
+ pt != NULL;
+ pt = pt ->Next) {
+
+ if (sig == pt -> Handler.Signature) return &pt ->Handler;
+ }
+
+ for (pt = DefaultLinkedList;
pt != NULL;
pt = pt ->Next) {
@@ -163,6 +158,7 @@
return TRUE;
}
+// Auxiliar to read an array of wchar_t
static
cmsBool _cmsReadWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, wchar_t* Array)
{
@@ -777,6 +773,8 @@
// Create memory
Text = (char*) _cmsMalloc(self ->ContextID, size);
+ if (Text == NULL) return FALSE;
+
cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text, size);
// Write it, including separator
@@ -1783,7 +1781,6 @@
if (!_cmsReadUInt8Number(io, NULL)) goto Error;
// Do some checking
-
if (InputChannels > cmsMAXCHANNELS) goto Error;
if (OutputChannels > cmsMAXCHANNELS) goto Error;
@@ -1824,9 +1821,16 @@
if (T == NULL) goto Error;
Temp = (cmsUInt8Number*) _cmsMalloc(self ->ContextID, nTabSize);
- if (Temp == NULL) goto Error;
-
- if (io ->Read(io, Temp, nTabSize, 1) != 1) goto Error;
+ if (Temp == NULL) {
+ _cmsFree(self ->ContextID, T);
+ goto Error;
+ }
+
+ if (io ->Read(io, Temp, nTabSize, 1) != 1) {
+ _cmsFree(self ->ContextID, T);
+ _cmsFree(self ->ContextID, Temp);
+ goto Error;
+ }
for (i = 0; i < nTabSize; i++) {
@@ -2371,27 +2375,30 @@
// Precision can be 1 or 2 bytes
if (Precision == 1) {
- cmsUInt8Number v;
+ cmsUInt8Number v;
for (i=0; i < Data ->nEntries; i++) {
- if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) return NULL;
- Data ->Tab.T[i] = FROM_8_TO_16(v);
+ if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) return NULL;
+ Data ->Tab.T[i] = FROM_8_TO_16(v);
}
}
else
if (Precision == 2) {
- if (!_cmsReadUInt16Array(io, Data->nEntries, Data ->Tab.T)) return NULL;
- }
- else {
- cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown precision of '%d'", Precision);
- return NULL;
- }
-
-
- return CLUT;
+ if (!_cmsReadUInt16Array(io, Data->nEntries, Data ->Tab.T)) {
+ cmsStageFree(CLUT);
+ return NULL;
+ }
+ }
+ else {
+ cmsStageFree(CLUT);
+ cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown precision of '%d'", Precision);
+ return NULL;
+ }
+
+ return CLUT;
}
static
@@ -4374,7 +4381,7 @@
{TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigCLutElemType, MPEclut), NULL },
};
-#define DEFAULT_MPE_TYPE_COUNT (sizeof(SupportedMPEtypes) / sizeof(_cmsTagTypeLinkedList))
+_cmsTagTypePluginChunkType _cmsMPETypePluginChunk = { NULL };
static
cmsBool ReadMPEElem(struct _cms_typehandler_struct* self,
@@ -4387,6 +4394,8 @@
cmsTagTypeHandler* TypeHandler;
cmsUInt32Number nItems;
cmsPipeline *NewLUT = (cmsPipeline *) Cargo;
+ _cmsTagTypePluginChunkType* MPETypePluginChunk = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(self->ContextID, MPEPlugin);
+
// Take signature and channels for each element.
if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) return FALSE;
@@ -4395,7 +4404,7 @@
if (!_cmsReadUInt32Number(io, NULL)) return FALSE;
// Read diverse MPE types
- TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, SupportedMPEtypes);
+ TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, MPETypePluginChunk ->TagTypes, SupportedMPEtypes);
if (TypeHandler == NULL) {
char String[5];
@@ -4472,6 +4481,7 @@
cmsPipeline* Lut = (cmsPipeline*) Ptr;
cmsStage* Elem = Lut ->Elements;
cmsTagTypeHandler* TypeHandler;
+ _cmsTagTypePluginChunkType* MPETypePluginChunk = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(self->ContextID, MPEPlugin);
BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
@@ -4505,7 +4515,7 @@
ElementSig = Elem ->Type;
- TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, SupportedMPEtypes);
+ TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, MPETypePluginChunk->TagTypes, SupportedMPEtypes);
if (TypeHandler == NULL) {
char String[5];
@@ -5125,7 +5135,7 @@
}
else {
- rc = cmsDictAddEntry(hDict, NameWCS, ValueWCS, DisplayNameMLU, DisplayValueMLU);
+ rc = cmsDictAddEntry(hDict, NameWCS, ValueWCS, DisplayNameMLU, DisplayValueMLU);
}
if (NameWCS != NULL) _cmsFree(self ->ContextID, NameWCS);
@@ -5282,24 +5292,95 @@
{TYPE_HANDLER(cmsSigVcgtType, vcgt), NULL }
};
-#define DEFAULT_TAG_TYPE_COUNT (sizeof(SupportedTagTypes) / sizeof(_cmsTagTypeLinkedList))
+
+_cmsTagTypePluginChunkType _cmsTagTypePluginChunk = { NULL };
+
+
+
+// Duplicates the zone of memory used by the plug-in in the new context
+static
+void DupTagTypeList(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src,
+ int loc)
+{
+ _cmsTagTypePluginChunkType newHead = { NULL };
+ _cmsTagTypeLinkedList* entry;
+ _cmsTagTypeLinkedList* Anterior = NULL;
+ _cmsTagTypePluginChunkType* head = (_cmsTagTypePluginChunkType*) src->chunks[loc];
+
+ // Walk the list copying all nodes
+ for (entry = head->TagTypes;
+ entry != NULL;
+ entry = entry ->Next) {
+
+ _cmsTagTypeLinkedList *newEntry = ( _cmsTagTypeLinkedList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTagTypeLinkedList));
+
+ if (newEntry == NULL)
+ return;
+
+ // We want to keep the linked list order, so this is a little bit tricky
+ newEntry -> Next = NULL;
+ if (Anterior)
+ Anterior -> Next = newEntry;
+
+ Anterior = newEntry;
+
+ if (newHead.TagTypes == NULL)
+ newHead.TagTypes = newEntry;
+ }
+
+ ctx ->chunks[loc] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTagTypePluginChunkType));
+}
+
+
+void _cmsAllocTagTypePluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ if (src != NULL) {
+
+ // Duplicate the LIST
+ DupTagTypeList(ctx, src, TagTypePlugin);
+ }
+ else {
+ static _cmsTagTypePluginChunkType TagTypePluginChunk = { NULL };
+ ctx ->chunks[TagTypePlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagTypePluginChunk, sizeof(_cmsTagTypePluginChunkType));
+ }
+}
+
+void _cmsAllocMPETypePluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ if (src != NULL) {
+
+ // Duplicate the LIST
+ DupTagTypeList(ctx, src, MPEPlugin);
+ }
+ else {
+ static _cmsTagTypePluginChunkType TagTypePluginChunk = { NULL };
+ ctx ->chunks[MPEPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagTypePluginChunk, sizeof(_cmsTagTypePluginChunkType));
+ }
+
+}
+
// Both kind of plug-ins share same structure
cmsBool _cmsRegisterTagTypePlugin(cmsContext id, cmsPluginBase* Data)
{
- return RegisterTypesPlugin(id, Data, SupportedTagTypes, DEFAULT_TAG_TYPE_COUNT);
+ return RegisterTypesPlugin(id, Data, TagTypePlugin);
}
cmsBool _cmsRegisterMultiProcessElementPlugin(cmsContext id, cmsPluginBase* Data)
{
- return RegisterTypesPlugin(id, Data, SupportedMPEtypes, DEFAULT_MPE_TYPE_COUNT);
+ return RegisterTypesPlugin(id, Data,MPEPlugin);
}
// Wrapper for tag types
-cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsTagTypeSignature sig)
-{
- return GetHandler(sig, SupportedTagTypes);
+cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsContext ContextID, cmsTagTypeSignature sig)
+{
+ _cmsTagTypePluginChunkType* ctx = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(ContextID, TagTypePlugin);
+
+ return GetHandler(sig, ctx->TagTypes, SupportedTagTypes);
}
// ********************************************************************************
@@ -5414,48 +5495,94 @@
cmsSigDeviceSettingsTag ==> Deprecated, useless
*/
-#define DEFAULT_TAG_COUNT (sizeof(SupportedTags) / sizeof(_cmsTagLinkedList))
+
+_cmsTagPluginChunkType _cmsTagPluginChunk = { NULL };
+
+
+// Duplicates the zone of memory used by the plug-in in the new context
+static
+void DupTagList(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ _cmsTagPluginChunkType newHead = { NULL };
+ _cmsTagLinkedList* entry;
+ _cmsTagLinkedList* Anterior = NULL;
+ _cmsTagPluginChunkType* head = (_cmsTagPluginChunkType*) src->chunks[TagPlugin];
+
+ // Walk the list copying all nodes
+ for (entry = head->Tag;
+ entry != NULL;
+ entry = entry ->Next) {
+
+ _cmsTagLinkedList *newEntry = ( _cmsTagLinkedList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTagLinkedList));
+
+ if (newEntry == NULL)
+ return;
+
+ // We want to keep the linked list order, so this is a little bit tricky
+ newEntry -> Next = NULL;
+ if (Anterior)
+ Anterior -> Next = newEntry;
+
+ Anterior = newEntry;
+
+ if (newHead.Tag == NULL)
+ newHead.Tag = newEntry;
+ }
+
+ ctx ->chunks[TagPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTagPluginChunkType));
+}
+
+void _cmsAllocTagPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ if (src != NULL) {
+
+ DupTagList(ctx, src);
+ }
+ else {
+ static _cmsTagPluginChunkType TagPluginChunk = { NULL };
+ ctx ->chunks[TagPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagPluginChunk, sizeof(_cmsTagPluginChunkType));
+ }
+
+}
cmsBool _cmsRegisterTagPlugin(cmsContext id, cmsPluginBase* Data)
{
cmsPluginTag* Plugin = (cmsPluginTag*) Data;
- _cmsTagLinkedList *pt, *Anterior;
-
+ _cmsTagLinkedList *pt;
+ _cmsTagPluginChunkType* TagPluginChunk = ( _cmsTagPluginChunkType*) _cmsContextGetClientChunk(id, TagPlugin);
if (Data == NULL) {
- SupportedTags[DEFAULT_TAG_COUNT-1].Next = NULL;
+ TagPluginChunk->Tag = NULL;
return TRUE;
}
- pt = Anterior = SupportedTags;
- while (pt != NULL) {
-
- if (Plugin->Signature == pt -> Signature) {
- pt ->Descriptor = Plugin ->Descriptor; // Replace old behaviour
- return TRUE;
- }
-
- Anterior = pt;
- pt = pt ->Next;
- }
-
pt = (_cmsTagLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagLinkedList));
if (pt == NULL) return FALSE;
pt ->Signature = Plugin ->Signature;
pt ->Descriptor = Plugin ->Descriptor;
- pt ->Next = NULL;
-
- if (Anterior != NULL) Anterior -> Next = pt;
+ pt ->Next = TagPluginChunk ->Tag;
+
+ TagPluginChunk ->Tag = pt;
return TRUE;
}
// Return a descriptor for a given tag or NULL
-cmsTagDescriptor* _cmsGetTagDescriptor(cmsTagSignature sig)
+cmsTagDescriptor* _cmsGetTagDescriptor(cmsContext ContextID, cmsTagSignature sig)
{
_cmsTagLinkedList* pt;
+ _cmsTagPluginChunkType* TagPluginChunk = ( _cmsTagPluginChunkType*) _cmsContextGetClientChunk(ContextID, TagPlugin);
+
+ for (pt = TagPluginChunk->Tag;
+ pt != NULL;
+ pt = pt ->Next) {
+
+ if (sig == pt -> Signature) return &pt ->Descriptor;
+ }
for (pt = SupportedTags;
pt != NULL;
--- a/jdk/src/java.desktop/share/native/liblcms/cmsvirt.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/cmsvirt.c Wed Jul 05 20:01:44 2017 +0200
@@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
-// Copyright (c) 1998-2011 Marti Maria Saguer
+// Copyright (c) 1998-2014 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@@ -1019,7 +1019,7 @@
static const cmsAllowedLUT AllowedLUTTypes[] = {
- { FALSE, 0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}},
+ { FALSE, 0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}},
{ FALSE, 0, cmsSigLut16Type, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}},
{ FALSE, 0, cmsSigLut16Type, 2, { cmsSigCurveSetElemType, cmsSigCLutElemType}},
{ TRUE , 0, cmsSigLutAtoBType, 1, { cmsSigCurveSetElemType }},
@@ -1150,7 +1150,7 @@
if (AllowedLUT == NULL) {
// Try to optimize
- _cmsOptimizePipeline(&LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags);
+ _cmsOptimizePipeline(ContextID, &LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags);
AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag);
}
@@ -1159,7 +1159,7 @@
if (AllowedLUT == NULL) {
dwFlags |= cmsFLAGS_FORCE_CLUT;
- _cmsOptimizePipeline(&LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags);
+ _cmsOptimizePipeline(ContextID, &LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags);
// Put identity curves if needed
if (cmsPipelineGetPtrToFirstStage(LUT) ->Type != cmsSigCurveSetElemType)
--- a/jdk/src/java.desktop/share/native/liblcms/cmswtpnt.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/cmswtpnt.c Wed Jul 05 20:01:44 2017 +0200
@@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
-// Copyright (c) 1998-2012 Marti Maria Saguer
+// Copyright (c) 1998-2014 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
--- a/jdk/src/java.desktop/share/native/liblcms/cmsxform.c Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/cmsxform.c Wed Jul 05 20:01:44 2017 +0200
@@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
-// Copyright (c) 1998-2011 Marti Maria Saguer
+// Copyright (c) 1998-2014 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@@ -58,44 +58,120 @@
// Transformations stuff
// -----------------------------------------------------------------------
-// Alarm codes for 16-bit transformations, because the fixed range of containers there are
-// no values left to mark out of gamut. volatile is C99 per 6.2.5
-static volatile cmsUInt16Number Alarm[cmsMAXCHANNELS] = { 0x7F00, 0x7F00, 0x7F00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-static volatile cmsFloat64Number GlobalAdaptationState = 1;
+#define DEFAULT_OBSERVER_ADAPTATION_STATE 1.0
+
+// The Context0 observer adaptation state.
+_cmsAdaptationStateChunkType _cmsAdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE };
+
+// Init and duplicate observer adaptation state
+void _cmsAllocAdaptationStateChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ static _cmsAdaptationStateChunkType AdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE };
+ void* from;
+
+ if (src != NULL) {
+ from = src ->chunks[AdaptationStateContext];
+ }
+ else {
+ from = &AdaptationStateChunk;
+ }
+
+ ctx ->chunks[AdaptationStateContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAdaptationStateChunkType));
+}
+
+
+// Sets adaptation state for absolute colorimetric intent in the given context. Adaptation state applies on all
+// but cmsCreateExtendedTransformTHR(). Little CMS can handle incomplete adaptation states.
+cmsFloat64Number CMSEXPORT cmsSetAdaptationStateTHR(cmsContext ContextID, cmsFloat64Number d)
+{
+ cmsFloat64Number prev;
+ _cmsAdaptationStateChunkType* ptr = (_cmsAdaptationStateChunkType*) _cmsContextGetClientChunk(ContextID, AdaptationStateContext);
+
+ // Get previous value for return
+ prev = ptr ->AdaptationState;
+
+ // Set the value if d is positive or zero
+ if (d >= 0.0) {
+
+ ptr ->AdaptationState = d;
+ }
+
+ // Always return previous value
+ return prev;
+}
+
// The adaptation state may be defaulted by this function. If you don't like it, use the extended transform routine
cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsFloat64Number d)
{
- cmsFloat64Number OldVal = GlobalAdaptationState;
-
- if (d >= 0)
- GlobalAdaptationState = d;
-
- return OldVal;
+ return cmsSetAdaptationStateTHR(NULL, d);
}
-// Alarm codes are always global
-void CMSEXPORT cmsSetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS])
+// -----------------------------------------------------------------------
+
+// Alarm codes for 16-bit transformations, because the fixed range of containers there are
+// no values left to mark out of gamut.
+
+#define DEFAULT_ALARM_CODES_VALUE {0x7F00, 0x7F00, 0x7F00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+
+_cmsAlarmCodesChunkType _cmsAlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE };
+
+// Sets the codes used to mark out-out-gamut on Proofing transforms for a given context. Values are meant to be
+// encoded in 16 bits.
+void CMSEXPORT cmsSetAlarmCodesTHR(cmsContext ContextID, const cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS])
{
- int i;
+ _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext);
+
+ _cmsAssert(ContextAlarmCodes != NULL); // Can't happen
+
+ memcpy(ContextAlarmCodes->AlarmCodes, AlarmCodesP, sizeof(ContextAlarmCodes->AlarmCodes));
+}
+// Gets the current codes used to mark out-out-gamut on Proofing transforms for the given context.
+// Values are meant to be encoded in 16 bits.
+void CMSEXPORT cmsGetAlarmCodesTHR(cmsContext ContextID, cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS])
+{
+ _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext);
+
+ _cmsAssert(ContextAlarmCodes != NULL); // Can't happen
+
+ memcpy(AlarmCodesP, ContextAlarmCodes->AlarmCodes, sizeof(ContextAlarmCodes->AlarmCodes));
+}
+
+void CMSEXPORT cmsSetAlarmCodes(const cmsUInt16Number NewAlarm[cmsMAXCHANNELS])
+{
_cmsAssert(NewAlarm != NULL);
- for (i=0; i < cmsMAXCHANNELS; i++)
- Alarm[i] = NewAlarm[i];
+ cmsSetAlarmCodesTHR(NULL, NewAlarm);
}
-// You can get the codes cas well
void CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number OldAlarm[cmsMAXCHANNELS])
{
- int i;
+ _cmsAssert(OldAlarm != NULL);
+ cmsGetAlarmCodesTHR(NULL, OldAlarm);
+}
+
- _cmsAssert(OldAlarm != NULL);
+// Init and duplicate alarm codes
+void _cmsAllocAlarmCodesChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ static _cmsAlarmCodesChunkType AlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE };
+ void* from;
- for (i=0; i < cmsMAXCHANNELS; i++)
- OldAlarm[i] = Alarm[i];
+ if (src != NULL) {
+ from = src ->chunks[AlarmCodesContext];
+ }
+ else {
+ from = &AlarmCodesChunk;
+ }
+
+ ctx ->chunks[AlarmCodesContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAlarmCodesChunkType));
}
+// -----------------------------------------------------------------------
+
// Get rid of transform resources
void CMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform)
{
@@ -202,6 +278,30 @@
}
}
+
+static
+void NullFloatXFORM(_cmsTRANSFORM* p,
+ const void* in,
+ void* out,
+ cmsUInt32Number Size,
+ cmsUInt32Number Stride)
+{
+ cmsUInt8Number* accum;
+ cmsUInt8Number* output;
+ cmsFloat32Number fIn[cmsMAXCHANNELS];
+ cmsUInt32Number i, n;
+
+ accum = (cmsUInt8Number*) in;
+ output = (cmsUInt8Number*) out;
+ n = Size;
+
+ for (i=0; i < n; i++) {
+
+ accum = p -> FromInputFloat(p, fIn, accum, Stride);
+ output = p -> ToOutputFloat(p, fIn, output, Stride);
+ }
+}
+
// 16 bit precision -----------------------------------------------------------------------------------------------------------
// Null transformation, only applies formatters. No caché
@@ -252,7 +352,7 @@
}
-// Auxiliar: Handle precalculated gamut check
+// Auxiliar: Handle precalculated gamut check. The retrieval of context may be alittle bit slow, but this function is not critical.
static
void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p,
const cmsUInt16Number wIn[],
@@ -264,9 +364,12 @@
if (wOutOfGamut >= 1) {
cmsUInt16Number i;
+ _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(p->ContextID, AlarmCodesContext);
- for (i=0; i < p ->Lut->OutputChannels; i++)
- wOut[i] = Alarm[i];
+ for (i=0; i < p ->Lut->OutputChannels; i++) {
+
+ wOut[i] = ContextAlarmCodes ->AlarmCodes[i];
+ }
}
else
p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data);
@@ -393,34 +496,86 @@
} _cmsTransformCollection;
// The linked list head
-static _cmsTransformCollection* TransformCollection = NULL;
+_cmsTransformPluginChunkType _cmsTransformPluginChunk = { NULL };
+
+
+// Duplicates the zone of memory used by the plug-in in the new context
+static
+void DupPluginTransformList(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ _cmsTransformPluginChunkType newHead = { NULL };
+ _cmsTransformCollection* entry;
+ _cmsTransformCollection* Anterior = NULL;
+ _cmsTransformPluginChunkType* head = (_cmsTransformPluginChunkType*) src->chunks[TransformPlugin];
+
+ // Walk the list copying all nodes
+ for (entry = head->TransformCollection;
+ entry != NULL;
+ entry = entry ->Next) {
+
+ _cmsTransformCollection *newEntry = ( _cmsTransformCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTransformCollection));
+
+ if (newEntry == NULL)
+ return;
+
+ // We want to keep the linked list order, so this is a little bit tricky
+ newEntry -> Next = NULL;
+ if (Anterior)
+ Anterior -> Next = newEntry;
+
+ Anterior = newEntry;
+
+ if (newHead.TransformCollection == NULL)
+ newHead.TransformCollection = newEntry;
+ }
+
+ ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTransformPluginChunkType));
+}
+
+void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ if (src != NULL) {
+
+ // Copy all linked list
+ DupPluginTransformList(ctx, src);
+ }
+ else {
+ static _cmsTransformPluginChunkType TransformPluginChunkType = { NULL };
+ ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TransformPluginChunkType, sizeof(_cmsTransformPluginChunkType));
+ }
+}
+
+
// Register new ways to transform
-cmsBool _cmsRegisterTransformPlugin(cmsContext id, cmsPluginBase* Data)
+cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Data)
{
cmsPluginTransform* Plugin = (cmsPluginTransform*) Data;
_cmsTransformCollection* fl;
+ _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID,TransformPlugin);
- if (Data == NULL) {
+ if (Data == NULL) {
// Free the chain. Memory is safely freed at exit
- TransformCollection = NULL;
+ ctx->TransformCollection = NULL;
return TRUE;
}
// Factory callback is required
- if (Plugin ->Factory == NULL) return FALSE;
+ if (Plugin ->Factory == NULL) return FALSE;
- fl = (_cmsTransformCollection*) _cmsPluginMalloc(id, sizeof(_cmsTransformCollection));
+ fl = (_cmsTransformCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsTransformCollection));
if (fl == NULL) return FALSE;
- // Copy the parameters
+ // Copy the parameters
fl ->Factory = Plugin ->Factory;
// Keep linked list
- fl ->Next = TransformCollection;
- TransformCollection = fl;
+ fl ->Next = ctx->TransformCollection;
+ ctx->TransformCollection = fl;
// All is ok
return TRUE;
@@ -463,6 +618,7 @@
_cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
{
+ _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID, TransformPlugin);
_cmsTransformCollection* Plugin;
// Allocate needed memory
@@ -473,7 +629,7 @@
p ->Lut = lut;
// Let's see if any plug-in want to do the transform by itself
- for (Plugin = TransformCollection;
+ for (Plugin = ctx ->TransformCollection;
Plugin != NULL;
Plugin = Plugin ->Next) {
@@ -493,10 +649,10 @@
// Fill the formatters just in case the optimized routine is interested.
// No error is thrown if the formatter doesn't exist. It is up to the optimization
// factory to decide what to do in those cases.
- p ->FromInput = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
- p ->ToOutput = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
- p ->FromInputFloat = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
- p ->ToOutputFloat = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
+ p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
+ p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
+ p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
+ p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
return p;
}
@@ -504,14 +660,14 @@
// Not suitable for the transform plug-in, let's check the pipeline plug-in
if (p ->Lut != NULL)
- _cmsOptimizePipeline(&p->Lut, Intent, InputFormat, OutputFormat, dwFlags);
+ _cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags);
// Check whatever this is a true floating point transform
if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) {
// Get formatter function always return a valid union, but the contents of this union may be NULL.
- p ->FromInputFloat = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
- p ->ToOutputFloat = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
+ p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
+ p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
*dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) {
@@ -521,8 +677,15 @@
return NULL;
}
- // Float transforms don't use caché, always are non-NULL
- p ->xform = FloatXFORM;
+ if (*dwFlags & cmsFLAGS_NULLTRANSFORM) {
+
+ p ->xform = NullFloatXFORM;
+ }
+ else {
+ // Float transforms don't use caché, always are non-NULL
+ p ->xform = FloatXFORM;
+ }
+
}
else {
@@ -534,8 +697,8 @@
int BytesPerPixelInput;
- p ->FromInput = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
- p ->ToOutput = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
+ p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
+ p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
if (p ->FromInput == NULL || p ->ToOutput == NULL) {
@@ -727,6 +890,7 @@
// Check channel count
if ((cmsChannelsOf(EntryColorSpace) != cmsPipelineInputChannels(Lut)) ||
(cmsChannelsOf(ExitColorSpace) != cmsPipelineOutputChannels(Lut))) {
+ cmsPipelineFree(Lut);
cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Channel count doesn't match. Profile is corrupted");
return NULL;
}
@@ -829,7 +993,7 @@
for (i=0; i < nProfiles; i++) {
BPC[i] = dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION ? TRUE : FALSE;
Intents[i] = Intent;
- AdaptationStates[i] = GlobalAdaptationState;
+ AdaptationStates[i] = cmsSetAdaptationStateTHR(ContextID, -1);
}
@@ -909,7 +1073,7 @@
Intents[0] = nIntent; Intents[1] = nIntent; Intents[2] = INTENT_RELATIVE_COLORIMETRIC; Intents[3] = ProofingIntent;
BPC[0] = DoBPC; BPC[1] = DoBPC; BPC[2] = 0; BPC[3] = 0;
- Adaptation[0] = Adaptation[1] = Adaptation[2] = Adaptation[3] = GlobalAdaptationState;
+ Adaptation[0] = Adaptation[1] = Adaptation[2] = Adaptation[3] = cmsSetAdaptationStateTHR(ContextID, -1);
if (!(dwFlags & (cmsFLAGS_SOFTPROOFING|cmsFLAGS_GAMUTCHECK)))
return cmsCreateTransformTHR(ContextID, InputProfile, InputFormat, OutputProfile, OutputFormat, nIntent, dwFlags);
@@ -984,8 +1148,8 @@
return FALSE;
}
- FromInput = _cmsGetFormatter(InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
- ToOutput = _cmsGetFormatter(OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
+ FromInput = _cmsGetFormatter(xform->ContextID, InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
+ ToOutput = _cmsGetFormatter(xform->ContextID, OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
if (FromInput == NULL || ToOutput == NULL) {
--- a/jdk/src/java.desktop/share/native/liblcms/lcms2.h Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/lcms2.h Wed Jul 05 20:01:44 2017 +0200
@@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
-// Copyright (c) 1998-2013 Marti Maria Saguer
+// Copyright (c) 1998-2014 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@@ -52,7 +52,7 @@
//
//---------------------------------------------------------------------------------
//
-// Version 2.5
+// Version 2.6
//
#ifndef _lcms2_H
@@ -84,6 +84,9 @@
// Uncomment to get rid of the tables for "half" float support
// #define CMS_NO_HALF_SUPPORT 1
+// Uncomment to get rid of pthreads/windows dependency
+// #define CMS_NO_PTHREADS 1
+
// ********** End of configuration toggles ******************************
// Needed for streams
@@ -101,7 +104,7 @@
#endif
// Version/release
-#define LCMS_VERSION 2050
+#define LCMS_VERSION 2060
// I will give the chance of redefining basic types for compilers that are not fully C99 compliant
#ifndef CMS_BASIC_TYPES_ALREADY_DEFINED
@@ -202,28 +205,42 @@
// Try to detect big endian platforms. This list can be endless, so only some checks are performed over here.
// you can pass this toggle to the compiler by using -DCMS_USE_BIG_ENDIAN or something similar
-#if defined(_HOST_BIG_ENDIAN) || defined(__BIG_ENDIAN__) || defined(WORDS_BIGENDIAN)
-# define CMS_USE_BIG_ENDIAN 1
-#endif
-
-#if defined(__sgi__) || defined(__sgi) || defined(__powerpc__) || defined(sparc)
+#if defined(__sgi__) || defined(__sgi) || defined(sparc)
# define CMS_USE_BIG_ENDIAN 1
#endif
-#if defined(__ppc__) || defined(__s390__) || defined(__s390x__)
+#if defined(__s390__) || defined(__s390x__)
# define CMS_USE_BIG_ENDIAN 1
#endif
-#ifdef TARGET_CPU_PPC
-# if TARGET_CPU_PPC
+# ifdef TARGET_CPU_PPC
+# if TARGET_CPU_PPC
+# define CMS_USE_BIG_ENDIAN 1
+# endif
+# endif
+
+#if defined(__powerpc__) || defined(__ppc__) || defined(TARGET_CPU_PPC)
# define CMS_USE_BIG_ENDIAN 1
-# endif
+# if defined (__GNUC__) && defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN)
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+// // Don't use big endian for PowerPC little endian mode
+# undef CMS_USE_BIG_ENDIAN
+# endif
+# endif
+#endif
+
+// WORDS_BIGENDIAN takes precedence
+#if defined(_HOST_BIG_ENDIAN) || defined(__BIG_ENDIAN__) || defined(WORDS_BIGENDIAN)
+# define CMS_USE_BIG_ENDIAN 1
#endif
#ifdef macintosh
# ifdef __BIG_ENDIAN__
# define CMS_USE_BIG_ENDIAN 1
# endif
+# ifdef __LITTLE_ENDIAN__
+# undef CMS_USE_BIG_ENDIAN
+# endif
#endif
// Calling convention -- this is hardly platform and compiler dependent
@@ -249,6 +266,14 @@
# define CMSAPI
#endif
+#ifdef HasTHREADS
+# if HasTHREADS == 1
+# undef CMS_NO_PTHREADS
+# else
+# define CMS_NO_PTHREADS 1
+# endif
+#endif
+
// Some common definitions
#define cmsMAX_PATH 256
@@ -642,7 +667,6 @@
// Little CMS specific typedefs
-typedef void* cmsContext; // Context identifier for multithreaded environments
typedef void* cmsHANDLE ; // Generic handle
typedef void* cmsHPROFILE; // Opaque typedefs to hide internals
typedef void* cmsHTRANSFORM;
@@ -1012,11 +1036,25 @@
CMSAPI int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2);
CMSAPI long int CMSEXPORT cmsfilelength(FILE* f);
-// Plug-In registering ---------------------------------------------------------------------------------------------------
+
+// Context handling --------------------------------------------------------------------------------------------------------
+
+// Each context holds its owns globals and its own plug-ins. There is a global context with the id = 0 for lecacy compatibility
+// though using the global context is not recomended. Proper context handling makes lcms more thread-safe.
+
+typedef struct _cmsContext_struct* cmsContext;
+
+CMSAPI cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData);
+CMSAPI void CMSEXPORT cmsDeleteContext(cmsContext ContexID);
+CMSAPI cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData);
+CMSAPI void* CMSEXPORT cmsGetContextUserData(cmsContext ContextID);
+
+// Plug-In registering --------------------------------------------------------------------------------------------------
CMSAPI cmsBool CMSEXPORT cmsPlugin(void* Plugin);
CMSAPI cmsBool CMSEXPORT cmsPluginTHR(cmsContext ContextID, void* Plugin);
CMSAPI void CMSEXPORT cmsUnregisterPlugins(void);
+CMSAPI void CMSEXPORT cmsUnregisterPluginsTHR(cmsContext ContextID);
// Error logging ----------------------------------------------------------------------------------------------------------
@@ -1053,6 +1091,7 @@
// Allows user to set any specific logger
CMSAPI void CMSEXPORT cmsSetLogErrorHandler(cmsLogErrorHandlerFunction Fn);
+CMSAPI void CMSEXPORT cmsSetLogErrorHandlerTHR(cmsContext ContextID, cmsLogErrorHandlerFunction Fn);
// Conversions --------------------------------------------------------------------------------------------------------------
@@ -1514,6 +1553,7 @@
CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromMem(const void * MemPtr, cmsUInt32Number dwSize);
CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromMemTHR(cmsContext ContextID, const void * MemPtr, cmsUInt32Number dwSize);
CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromIOhandlerTHR(cmsContext ContextID, cmsIOHANDLER* io);
+CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromIOhandler2THR(cmsContext ContextID, cmsIOHANDLER* io, cmsBool write);
CMSAPI cmsBool CMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile);
CMSAPI cmsBool CMSEXPORT cmsSaveProfileToFile(cmsHPROFILE hProfile, const char* FileName);
@@ -1604,6 +1644,7 @@
// Call with NULL as parameters to get the intent count
CMSAPI cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions);
+CMSAPI cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID, cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions);
// Flags
@@ -1715,11 +1756,22 @@
cmsUInt32Number Stride);
-CMSAPI void CMSEXPORT cmsSetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS]);
+CMSAPI void CMSEXPORT cmsSetAlarmCodes(const cmsUInt16Number NewAlarm[cmsMAXCHANNELS]);
CMSAPI void CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS]);
+
+CMSAPI void CMSEXPORT cmsSetAlarmCodesTHR(cmsContext ContextID,
+ const cmsUInt16Number AlarmCodes[cmsMAXCHANNELS]);
+CMSAPI void CMSEXPORT cmsGetAlarmCodesTHR(cmsContext ContextID,
+ cmsUInt16Number AlarmCodes[cmsMAXCHANNELS]);
+
+
+
// Adaptation state for absolute colorimetric intent
CMSAPI cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsFloat64Number d);
+CMSAPI cmsFloat64Number CMSEXPORT cmsSetAdaptationStateTHR(cmsContext ContextID, cmsFloat64Number d);
+
+
// Grab the ContextID from an open transform. Returns NULL if a NULL transform is passed
CMSAPI cmsContext CMSEXPORT cmsGetTransformContextID(cmsHTRANSFORM hTransform);
--- a/jdk/src/java.desktop/share/native/liblcms/lcms2_internal.h Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/lcms2_internal.h Wed Jul 05 20:01:44 2017 +0200
@@ -30,7 +30,7 @@
//
// Little Color Management System
-// Copyright (c) 1998-2011 Marti Maria Saguer
+// Copyright (c) 1998-2014 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@@ -193,16 +193,171 @@
return _cmsQuickFloorWord(d);
}
-// Plug-In registering ---------------------------------------------------------------
+
+// Pthread support --------------------------------------------------------------------
+#ifndef CMS_NO_PTHREADS
+
+// This is the threading support. Unfortunately, it has to be platform-dependent because
+// windows does not support pthreads.
+
+#ifdef CMS_IS_WINDOWS_
+
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+
+
+// From: http://locklessinc.com/articles/pthreads_on_windows/
+// The pthreads API has an initialization macro that has no correspondence to anything in
+// the windows API. By investigating the internal definition of the critical section type,
+// one may work out how to initialize one without calling InitializeCriticalSection().
+// The trick here is that InitializeCriticalSection() is not allowed to fail. It tries
+// to allocate a critical section debug object, but if no memory is available, it sets
+// the pointer to a specific value. (One would expect that value to be NULL, but it is
+// actually (void *)-1 for some reason.) Thus we can use this special value for that
+// pointer, and the critical section code will work.
+
+// The other important part of the critical section type to initialize is the number
+// of waiters. This controls whether or not the mutex is locked. Fortunately, this
+// part of the critical section is unlikely to change. Apparently, many programs
+// already test critical sections to see if they are locked using this value, so
+// Microsoft felt that it was necessary to keep it set at -1 for an unlocked critical
+// section, even when they changed the underlying algorithm to be more scalable.
+// The final parts of the critical section object are unimportant, and can be set
+// to zero for their defaults. This yields an initialization macro:
+
+typedef CRITICAL_SECTION _cmsMutex;
+
+#define CMS_MUTEX_INITIALIZER {(void*) -1,-1,0,0,0,0}
+
+cmsINLINE int _cmsLockPrimitive(_cmsMutex *m)
+{
+ EnterCriticalSection(m);
+ return 0;
+}
+
+cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m)
+{
+ LeaveCriticalSection(m);
+ return 0;
+}
+
+cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m)
+{
+ InitializeCriticalSection(m);
+ return 0;
+}
+
+cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m)
+{
+ DeleteCriticalSection(m);
+ return 0;
+}
+
+cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m)
+{
+ EnterCriticalSection(m);
+ return 0;
+}
+
+cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m)
+{
+ LeaveCriticalSection(m);
+ return 0;
+}
+
+#else
+
+// Rest of the wide world
+#include <pthread.h>
+
+#define CMS_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+typedef pthread_mutex_t _cmsMutex;
+
+
+cmsINLINE int _cmsLockPrimitive(_cmsMutex *m)
+{
+ return pthread_mutex_lock(m);
+}
+
+cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m)
+{
+ return pthread_mutex_unlock(m);
+}
+
+cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m)
+{
+ return pthread_mutex_init(m, NULL);
+}
+
+cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m)
+{
+ return pthread_mutex_destroy(m);
+}
+
+cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m)
+{
+ return pthread_mutex_lock(m);
+}
+
+cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m)
+{
+ return pthread_mutex_unlock(m);
+}
+
+#endif
+#else
+
+#define CMS_MUTEX_INITIALIZER 0
+typedef int _cmsMutex;
+
+
+cmsINLINE int _cmsLockPrimitive(_cmsMutex *m)
+{
+ return 0;
+ cmsUNUSED_PARAMETER(m);
+}
+
+cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m)
+{
+ return 0;
+ cmsUNUSED_PARAMETER(m);
+}
+
+cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m)
+{
+ return 0;
+ cmsUNUSED_PARAMETER(m);
+}
+
+cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m)
+{
+ return 0;
+ cmsUNUSED_PARAMETER(m);
+}
+
+cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m)
+{
+ return 0;
+ cmsUNUSED_PARAMETER(m);
+}
+
+cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m)
+{
+ return 0;
+ cmsUNUSED_PARAMETER(m);
+}
+#endif
+
+// Plug-In registration ---------------------------------------------------------------
// Specialized function for plug-in memory management. No pairing free() since whole pool is freed at once.
void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size);
// Memory management
-cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin);
+cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// Interpolation
-cmsBool _cmsRegisterInterpPlugin(cmsPluginBase* Plugin);
+cmsBool _cmsRegisterInterpPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// Parametric curves
cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
@@ -228,9 +383,12 @@
// Transform
cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
+// Mutex
+cmsBool _cmsRegisterMutexPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
+
// ---------------------------------------------------------------------------------------------------------
-// Suballocators. Those are blocks of memory that is freed at the end on whole block.
+// Suballocators.
typedef struct _cmsSubAllocator_chunk_st {
cmsUInt8Number* Block;
@@ -253,9 +411,264 @@
_cmsSubAllocator* _cmsCreateSubAlloc(cmsContext ContextID, cmsUInt32Number Initial);
void _cmsSubAllocDestroy(_cmsSubAllocator* s);
void* _cmsSubAlloc(_cmsSubAllocator* s, cmsUInt32Number size);
+void* _cmsSubAllocDup(_cmsSubAllocator* s, const void *ptr, cmsUInt32Number size);
// ----------------------------------------------------------------------------------
+// The context clients.
+typedef enum {
+
+ UserPtr, // User-defined pointer
+ Logger,
+ AlarmCodesContext,
+ AdaptationStateContext,
+ MemPlugin,
+ InterpPlugin,
+ CurvesPlugin,
+ FormattersPlugin,
+ TagTypePlugin,
+ TagPlugin,
+ IntentPlugin,
+ MPEPlugin,
+ OptimizationPlugin,
+ TransformPlugin,
+ MutexPlugin,
+
+ // Last in list
+ MemoryClientMax
+
+} _cmsMemoryClient;
+
+
+// Container for memory management plug-in.
+typedef struct {
+
+ _cmsMallocFnPtrType MallocPtr;
+ _cmsMalloZerocFnPtrType MallocZeroPtr;
+ _cmsFreeFnPtrType FreePtr;
+ _cmsReallocFnPtrType ReallocPtr;
+ _cmsCallocFnPtrType CallocPtr;
+ _cmsDupFnPtrType DupPtr;
+
+} _cmsMemPluginChunkType;
+
+// Copy memory management function pointers from plug-in to chunk, taking care of missing routines
+void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkType* ptr);
+
+// Internal structure for context
+struct _cmsContext_struct {
+
+ struct _cmsContext_struct* Next; // Points to next context in the new style
+ _cmsSubAllocator* MemPool; // The memory pool that stores context data
+
+ void* chunks[MemoryClientMax]; // array of pointers to client chunks. Memory itself is hold in the suballocator.
+ // If NULL, then it reverts to global Context0
+
+ _cmsMemPluginChunkType DefaultMemoryManager; // The allocators used for creating the context itself. Cannot be overriden
+};
+
+// Returns a pointer to a valid context structure, including the global one if id is zero.
+// Verifies the magic number.
+struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID);
+
+// Returns the block assigned to the specific zone.
+void* _cmsContextGetClientChunk(cmsContext id, _cmsMemoryClient mc);
+
+
+// Chunks of context memory by plug-in client -------------------------------------------------------
+
+// Those structures encapsulates all variables needed by the several context clients (mostly plug-ins)
+
+// Container for error logger -- not a plug-in
+typedef struct {
+
+ cmsLogErrorHandlerFunction LogErrorHandler; // Set to NULL for Context0 fallback
+
+} _cmsLogErrorChunkType;
+
+// The global Context0 storage for error logger
+extern _cmsLogErrorChunkType _cmsLogErrorChunk;
+
+// Allocate and init error logger container.
+void _cmsAllocLogErrorChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// Container for alarm codes -- not a plug-in
+typedef struct {
+
+ cmsUInt16Number AlarmCodes[cmsMAXCHANNELS];
+
+} _cmsAlarmCodesChunkType;
+
+// The global Context0 storage for alarm codes
+extern _cmsAlarmCodesChunkType _cmsAlarmCodesChunk;
+
+// Allocate and init alarm codes container.
+void _cmsAllocAlarmCodesChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// Container for adaptation state -- not a plug-in
+typedef struct {
+
+ cmsFloat64Number AdaptationState;
+
+} _cmsAdaptationStateChunkType;
+
+// The global Context0 storage for adaptation state
+extern _cmsAdaptationStateChunkType _cmsAdaptationStateChunk;
+
+// Allocate and init adaptation state container.
+void _cmsAllocAdaptationStateChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+
+// The global Context0 storage for memory management
+extern _cmsMemPluginChunkType _cmsMemPluginChunk;
+
+// Allocate and init memory management container.
+void _cmsAllocMemPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// Container for interpolation plug-in
+typedef struct {
+
+ cmsInterpFnFactory Interpolators;
+
+} _cmsInterpPluginChunkType;
+
+// The global Context0 storage for interpolation plug-in
+extern _cmsInterpPluginChunkType _cmsInterpPluginChunk;
+
+// Allocate and init interpolation container.
+void _cmsAllocInterpPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// Container for parametric curves plug-in
+typedef struct {
+
+ struct _cmsParametricCurvesCollection_st* ParametricCurves;
+
+} _cmsCurvesPluginChunkType;
+
+// The global Context0 storage for tone curves plug-in
+extern _cmsCurvesPluginChunkType _cmsCurvesPluginChunk;
+
+// Allocate and init parametric curves container.
+void _cmsAllocCurvesPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// Container for formatters plug-in
+typedef struct {
+
+ struct _cms_formatters_factory_list* FactoryList;
+
+} _cmsFormattersPluginChunkType;
+
+// The global Context0 storage for formatters plug-in
+extern _cmsFormattersPluginChunkType _cmsFormattersPluginChunk;
+
+// Allocate and init formatters container.
+void _cmsAllocFormattersPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// This chunk type is shared by TagType plug-in and MPE Plug-in
+typedef struct {
+
+ struct _cmsTagTypeLinkedList_st* TagTypes;
+
+} _cmsTagTypePluginChunkType;
+
+
+// The global Context0 storage for tag types plug-in
+extern _cmsTagTypePluginChunkType _cmsTagTypePluginChunk;
+
+
+// The global Context0 storage for mult process elements plug-in
+extern _cmsTagTypePluginChunkType _cmsMPETypePluginChunk;
+
+// Allocate and init Tag types container.
+void _cmsAllocTagTypePluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+// Allocate and init MPE container.
+void _cmsAllocMPETypePluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+// Container for tag plug-in
+typedef struct {
+
+ struct _cmsTagLinkedList_st* Tag;
+
+} _cmsTagPluginChunkType;
+
+
+// The global Context0 storage for tag plug-in
+extern _cmsTagPluginChunkType _cmsTagPluginChunk;
+
+// Allocate and init Tag container.
+void _cmsAllocTagPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// Container for intents plug-in
+typedef struct {
+
+ struct _cms_intents_list* Intents;
+
+} _cmsIntentsPluginChunkType;
+
+
+// The global Context0 storage for intents plug-in
+extern _cmsIntentsPluginChunkType _cmsIntentsPluginChunk;
+
+// Allocate and init intents container.
+void _cmsAllocIntentsPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// Container for optimization plug-in
+typedef struct {
+
+ struct _cmsOptimizationCollection_st* OptimizationCollection;
+
+} _cmsOptimizationPluginChunkType;
+
+
+// The global Context0 storage for optimizers plug-in
+extern _cmsOptimizationPluginChunkType _cmsOptimizationPluginChunk;
+
+// Allocate and init optimizers container.
+void _cmsAllocOptimizationPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// Container for transform plug-in
+typedef struct {
+
+ struct _cmsTransformCollection_st* TransformCollection;
+
+} _cmsTransformPluginChunkType;
+
+// The global Context0 storage for full-transform replacement plug-in
+extern _cmsTransformPluginChunkType _cmsTransformPluginChunk;
+
+// Allocate and init transform container.
+void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// Container for mutex plug-in
+typedef struct {
+
+ _cmsCreateMutexFnPtrType CreateMutexPtr;
+ _cmsDestroyMutexFnPtrType DestroyMutexPtr;
+ _cmsLockMutexFnPtrType LockMutexPtr;
+ _cmsUnlockMutexFnPtrType UnlockMutexPtr;
+
+} _cmsMutexPluginChunkType;
+
+// The global Context0 storage for mutex plug-in
+extern _cmsMutexPluginChunkType _cmsMutexPluginChunk;
+
+// Allocate and init mutex container.
+void _cmsAllocMutexPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// ----------------------------------------------------------------------------------
// MLU internal representation
typedef struct {
@@ -347,10 +760,14 @@
cmsBool TagSaveAsRaw[MAX_TABLE_TAG]; // True to write uncooked
void * TagPtrs[MAX_TABLE_TAG];
cmsTagTypeHandler* TagTypeHandlers[MAX_TABLE_TAG]; // Same structure may be serialized on different types
- // depending on profile version, so we keep track of the // type handler for each tag in the list.
+ // depending on profile version, so we keep track of the
+ // type handler for each tag in the list.
// Special
cmsBool IsWrite;
+ // Keep a mutex for cmsReadTag -- Note that this only works if the user includes a mutex plugin
+ void * UsrMutex;
+
} _cmsICCPROFILE;
// IO helpers for profiles
@@ -359,9 +776,9 @@
int _cmsSearchTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, cmsBool lFollowLinks);
// Tag types
-cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsTagTypeSignature sig);
+cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsContext ContextID, cmsTagTypeSignature sig);
cmsTagTypeSignature _cmsGetTagTrueType(cmsHPROFILE hProfile, cmsTagSignature sig);
-cmsTagDescriptor* _cmsGetTagDescriptor(cmsTagSignature sig);
+cmsTagDescriptor* _cmsGetTagDescriptor(cmsContext ContextID, cmsTagSignature sig);
// Error logging ---------------------------------------------------------------------------------------------------------
@@ -372,7 +789,7 @@
cmsInterpParams* _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags);
cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID, const cmsUInt32Number nSamples[], int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags);
void _cmsFreeInterpParams(cmsInterpParams* p);
-cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p);
+cmsBool _cmsSetInterpolationRoutine(cmsContext ContextID, cmsInterpParams* p);
// Curves ----------------------------------------------------------------------------------------------------------------
@@ -503,7 +920,8 @@
cmsUInt16Number **Black,
cmsUInt32Number *nOutputs);
-cmsBool _cmsOptimizePipeline(cmsPipeline** Lut,
+cmsBool _cmsOptimizePipeline(cmsContext ContextID,
+ cmsPipeline** Lut,
int Intent,
cmsUInt32Number* InputFormat,
cmsUInt32Number* OutputFormat,
@@ -528,7 +946,8 @@
cmsBool _cmsFormatterIsFloat(cmsUInt32Number Type);
cmsBool _cmsFormatterIs8bit(cmsUInt32Number Type);
-cmsFormatter _cmsGetFormatter(cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8
+cmsFormatter _cmsGetFormatter(cmsContext ContextID,
+ cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8
cmsFormatterDirection Dir,
cmsUInt32Number dwFlags);
--- a/jdk/src/java.desktop/share/native/liblcms/lcms2_plugin.h Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/share/native/liblcms/lcms2_plugin.h Wed Jul 05 20:01:44 2017 +0200
@@ -231,6 +231,7 @@
#define cmsPluginMultiProcessElementSig 0x6D706548 // 'mpeH'
#define cmsPluginOptimizationSig 0x6F707448 // 'optH'
#define cmsPluginTransformSig 0x7A666D48 // 'xfmH'
+#define cmsPluginMutexSig 0x6D747A48 // 'mtxH'
typedef struct _cmsPluginBaseStruct {
@@ -247,19 +248,28 @@
//----------------------------------------------------------------------------------------------------------
// Memory handler. Each new plug-in type replaces current behaviour
+
+typedef void* (* _cmsMallocFnPtrType)(cmsContext ContextID, cmsUInt32Number size);
+typedef void (* _cmsFreeFnPtrType)(cmsContext ContextID, void *Ptr);
+typedef void* (* _cmsReallocFnPtrType)(cmsContext ContextID, void* Ptr, cmsUInt32Number NewSize);
+
+typedef void* (* _cmsMalloZerocFnPtrType)(cmsContext ContextID, cmsUInt32Number size);
+typedef void* (* _cmsCallocFnPtrType)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size);
+typedef void* (* _cmsDupFnPtrType)(cmsContext ContextID, const void* Org, cmsUInt32Number size);
+
typedef struct {
cmsPluginBase base;
// Required
- void * (* MallocPtr)(cmsContext ContextID, cmsUInt32Number size);
- void (* FreePtr)(cmsContext ContextID, void *Ptr);
- void * (* ReallocPtr)(cmsContext ContextID, void* Ptr, cmsUInt32Number NewSize);
+ _cmsMallocFnPtrType MallocPtr;
+ _cmsFreeFnPtrType FreePtr;
+ _cmsReallocFnPtrType ReallocPtr;
// Optional
- void * (* MallocZeroPtr)(cmsContext ContextID, cmsUInt32Number size);
- void * (* CallocPtr)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size);
- void * (* DupPtr)(cmsContext ContextID, const void* Org, cmsUInt32Number size);
+ _cmsMalloZerocFnPtrType MallocZeroPtr;
+ _cmsCallocFnPtrType CallocPtr;
+ _cmsDupFnPtrType DupPtr;
} cmsPluginMemHandler;
@@ -622,6 +632,29 @@
} cmsPluginTransform;
+//----------------------------------------------------------------------------------------------------------
+// Mutex
+
+typedef void* (* _cmsCreateMutexFnPtrType)(cmsContext ContextID);
+typedef void (* _cmsDestroyMutexFnPtrType)(cmsContext ContextID, void* mtx);
+typedef cmsBool (* _cmsLockMutexFnPtrType)(cmsContext ContextID, void* mtx);
+typedef void (* _cmsUnlockMutexFnPtrType)(cmsContext ContextID, void* mtx);
+
+typedef struct {
+ cmsPluginBase base;
+
+ _cmsCreateMutexFnPtrType CreateMutexPtr;
+ _cmsDestroyMutexFnPtrType DestroyMutexPtr;
+ _cmsLockMutexFnPtrType LockMutexPtr;
+ _cmsUnlockMutexFnPtrType UnlockMutexPtr;
+
+} cmsPluginMutex;
+
+CMSAPI void* CMSEXPORT _cmsCreateMutex(cmsContext ContextID);
+CMSAPI void CMSEXPORT _cmsDestroyMutex(cmsContext ContextID, void* mtx);
+CMSAPI cmsBool CMSEXPORT _cmsLockMutex(cmsContext ContextID, void* mtx);
+CMSAPI void CMSEXPORT _cmsUnlockMutex(cmsContext ContextID, void* mtx);
+
#ifndef CMS_USE_CPP_API
# ifdef __cplusplus
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java Wed Jul 05 20:01:44 2017 +0200
@@ -55,7 +55,6 @@
*/
private final static int AWT_MULTICLICK_SMUDGE = 4;
// ButtonXXX events stuff
- static int rbutton = 0;
static int lastX = 0, lastY = 0;
static long lastTime = 0;
static long lastButton = 0;
@@ -632,23 +631,6 @@
return res;
}
- /**
- * Returns true if this event is disabled and shouldn't be passed to Java.
- * Default implementation returns false for all events.
- */
- static int getRightButtonNumber() {
- if (rbutton == 0) { // not initialized yet
- XToolkit.awtLock();
- try {
- rbutton = XlibWrapper.XGetPointerMapping(XToolkit.getDisplay(), XlibWrapper.ibuffer, 3);
- }
- finally {
- XToolkit.awtUnlock();
- }
- }
- return rbutton;
- }
-
static int getMouseMovementSmudge() {
//TODO: It's possible to read corresponding settings
return AWT_MULTICLICK_SMUDGE;
@@ -716,11 +698,7 @@
/*
Check for popup trigger !!
*/
- if (lbutton == getRightButtonNumber() || lbutton > 2) {
- popupTrigger = true;
- } else {
- popupTrigger = false;
- }
+ popupTrigger = (lbutton == 3);
}
button = XConstants.buttons[lbutton - 1];
--- a/jdk/src/java.desktop/unix/classes/sun/awt/datatransfer/flavormap.properties Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-#
-# This properties file is used to initialize the default
-# java.awt.datatransfer.SystemFlavorMap. It contains the X11 platform-specific,
-# default mappings between common X11 selection atoms and platform-independent
-# MIME type strings, which will be converted into
-# java.awt.datatransfer.DataFlavors.
-#
-# The standard format is:
-#
-# <native>=<MIME type>,<MIME type>, ...
-#
-# <native> should be a string identifier that the native platform will
-# recognize as a valid data format. <MIME type> should specify both a MIME
-# primary type and a MIME subtype separated by a '/'. The MIME type may include
-# parameters, where each parameter is a key/value pair separated by '=', and
-# where each parameter to the MIME type is separated by a ';'.
-#
-# Because SystemFlavorMap implements FlavorTable, developers are free to
-# duplicate DataFlavor values and set multiple values for a single native by
-# separating them with ",". If a mapping contains a duplicate key or value,
-# earlier mappings which included this key or value will be preferred.
-#
-# Mappings whose values specify DataFlavors with primary MIME types of
-# "text", and which support the charset parameter, should specify the exact
-# format in which the native platform expects the data. The "charset"
-# parameter specifies the char to byte encoding, the "eoln" parameter
-# specifies the end-of-line marker, and the "terminators" parameter specifies
-# the number of terminating NUL bytes. Note that "eoln" and "terminators"
-# are not standardized MIME type parameters. They are specific to this file
-# format ONLY. They will not appear in any of the DataFlavors returned by the
-# SystemFlavorMap at the Java level.
-#
-# If the "charset" parameter is omitted, or has zero length, the platform
-# default encoding is assumed. If the "eoln" parameter is omitted, or has
-# zero length, "\n" is assumed. If the "terminators" parameter is omitted,
-# or has a value less than zero, zero is assumed.
-#
-# Upon initialization, the data transfer subsystem will record the specified
-# details of the native text format, but the default SystemFlavorMap will
-# present a large set of synthesized DataFlavors which map, in both
-# directions, to the native. After receiving data from the application in one
-# of the synthetic DataFlavors, the data transfer subsystem will transform
-# the data stream into the format specified in this file before passing the
-# transformed stream to the native system.
-#
-# Mappings whose values specify DataFlavors with primary MIME types of
-# "text", but which do not support the charset parameter, will be treated as
-# opaque, 8-bit data. They will not undergo any transformation process, and
-# any "charset", "eoln", or "terminators" parameters specified in this file
-# will be ignored.
-#
-# See java.awt.datatransfer.DataFlavor.selectBestTextFlavor for a list of
-# text flavors which support the charset parameter.
-
-UTF8_STRING=text/plain;charset=UTF-8;eoln="\n";terminators=0
-
-# The COMPOUND_TEXT support for inter-client text transfer is disabled by
-# default. The reason is that many native applications prefer this format over
-# other native text formats, but are unable to decode the textual data in this
-# format properly. This results in java-to-native text transfer failures.
-# To enable the COMPOUND_TEXT support for this JRE installation uncomment
-# the line below.
-
-# COMPOUND_TEXT=text/plain;charset=x-compound-text;eoln="\n";terminators=0
-
-TEXT=text/plain;eoln="\n";terminators=0
-STRING=text/plain;charset=iso8859-1;eoln="\n";terminators=0
-FILE_NAME=application/x-java-file-list;class=java.util.List
-text/uri-list=application/x-java-file-list;class=java.util.List
-PNG=image/x-java-image;class=java.awt.Image
-JFIF=image/x-java-image;class=java.awt.Image
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/unix/classes/sun/datatransfer/resources/flavormap.properties Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,71 @@
+#
+# This properties file is used to initialize the default
+# java.awt.datatransfer.SystemFlavorMap. It contains the X11 platform-specific,
+# default mappings between common X11 selection atoms and platform-independent
+# MIME type strings, which will be converted into
+# java.awt.datatransfer.DataFlavors.
+#
+# The standard format is:
+#
+# <native>=<MIME type>,<MIME type>, ...
+#
+# <native> should be a string identifier that the native platform will
+# recognize as a valid data format. <MIME type> should specify both a MIME
+# primary type and a MIME subtype separated by a '/'. The MIME type may include
+# parameters, where each parameter is a key/value pair separated by '=', and
+# where each parameter to the MIME type is separated by a ';'.
+#
+# Because SystemFlavorMap implements FlavorTable, developers are free to
+# duplicate DataFlavor values and set multiple values for a single native by
+# separating them with ",". If a mapping contains a duplicate key or value,
+# earlier mappings which included this key or value will be preferred.
+#
+# Mappings whose values specify DataFlavors with primary MIME types of
+# "text", and which support the charset parameter, should specify the exact
+# format in which the native platform expects the data. The "charset"
+# parameter specifies the char to byte encoding, the "eoln" parameter
+# specifies the end-of-line marker, and the "terminators" parameter specifies
+# the number of terminating NUL bytes. Note that "eoln" and "terminators"
+# are not standardized MIME type parameters. They are specific to this file
+# format ONLY. They will not appear in any of the DataFlavors returned by the
+# SystemFlavorMap at the Java level.
+#
+# If the "charset" parameter is omitted, or has zero length, the platform
+# default encoding is assumed. If the "eoln" parameter is omitted, or has
+# zero length, "\n" is assumed. If the "terminators" parameter is omitted,
+# or has a value less than zero, zero is assumed.
+#
+# Upon initialization, the data transfer subsystem will record the specified
+# details of the native text format, but the default SystemFlavorMap will
+# present a large set of synthesized DataFlavors which map, in both
+# directions, to the native. After receiving data from the application in one
+# of the synthetic DataFlavors, the data transfer subsystem will transform
+# the data stream into the format specified in this file before passing the
+# transformed stream to the native system.
+#
+# Mappings whose values specify DataFlavors with primary MIME types of
+# "text", but which do not support the charset parameter, will be treated as
+# opaque, 8-bit data. They will not undergo any transformation process, and
+# any "charset", "eoln", or "terminators" parameters specified in this file
+# will be ignored.
+#
+# See java.awt.datatransfer.DataFlavor.selectBestTextFlavor for a list of
+# text flavors which support the charset parameter.
+
+UTF8_STRING=text/plain;charset=UTF-8;eoln="\n";terminators=0
+
+# The COMPOUND_TEXT support for inter-client text transfer is disabled by
+# default. The reason is that many native applications prefer this format over
+# other native text formats, but are unable to decode the textual data in this
+# format properly. This results in java-to-native text transfer failures.
+# To enable the COMPOUND_TEXT support for this JRE installation uncomment
+# the line below.
+
+# COMPOUND_TEXT=text/plain;charset=x-compound-text;eoln="\n";terminators=0
+
+TEXT=text/plain;eoln="\n";terminators=0
+STRING=text/plain;charset=iso8859-1;eoln="\n";terminators=0
+FILE_NAME=application/x-java-file-list;class=java.util.List
+text/uri-list=application/x-java-file-list;class=java.util.List
+PNG=image/x-java-image;class=java.awt.Image
+JFIF=image/x-java-image;class=java.awt.Image
--- a/jdk/src/java.desktop/unix/classes/sun/java2d/xr/XRSolidSrcPict.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.desktop/unix/classes/sun/java2d/xr/XRSolidSrcPict.java Wed Jul 05 20:01:44 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -31,12 +31,14 @@
XRSurfaceData srcPict;
XRColor xrCol;
- int curPixVal = -1;
+ int curPixVal;
public XRSolidSrcPict(XRBackend con, int parentXid) {
this.con = con;
xrCol = new XRColor();
+ curPixVal = 0xFF000000;
+
int solidPixmap = con.createPixmap(parentXid, 32, 1, 1);
int solidSrcPictXID = con.createPicture(solidPixmap, XRUtils.PictStandardARGB32);
con.setPictureRepeat(solidSrcPictXID, XRUtils.RepeatNormal);
--- a/jdk/src/java.desktop/windows/classes/sun/awt/datatransfer/flavormap.properties Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-#
-# This properties file is used to initialize the default
-# java.awt.datatransfer.SystemFlavorMap. It contains the Win32 platform-
-# specific, default mappings between common Win32 Clipboard atoms and platform-
-# independent MIME type strings, which will be converted into
-# java.awt.datatransfer.DataFlavors.
-#
-# The standard format is:
-#
-# <native>=<MIME type>,<MIME type>, ...
-#
-# <native> should be a string identifier that the native platform will
-# recognize as a valid data format. <MIME type> should specify both a MIME
-# primary type and a MIME subtype separated by a '/'. The MIME type may include
-# parameters, where each parameter is a key/value pair separated by '=', and
-# where each parameter to the MIME type is separated by a ';'.
-#
-# Because SystemFlavorMap implements FlavorTable, developers are free to
-# duplicate DataFlavor values and set multiple values for a single native by
-# separating them with ",". If a mapping contains a duplicate key or value,
-# earlier mappings which included this key or value will be preferred.#
-# Mappings whose values specify DataFlavors with primary MIME types of
-# "text", and which support the charset parameter, should specify the exact
-# format in which the native platform expects the data. The "charset"
-# parameter specifies the char to byte encoding, the "eoln" parameter
-# specifies the end-of-line marker, and the "terminators" parameter specifies
-# the number of terminating NUL bytes. Note that "eoln" and "terminators"
-# are not standardized MIME type parameters. They are specific to this file
-# format ONLY. They will not appear in any of the DataFlavors returned by the
-# SystemFlavorMap at the Java level.
-#
-# If the "charset" parameter is omitted, or has zero length, the platform
-# default encoding is assumed. If the "eoln" parameter is omitted, or has
-# zero length, "\n" is assumed. If the "terminators" parameter is omitted,
-# or has a value less than zero, zero is assumed.
-#
-# Upon initialization, the data transfer subsystem will record the specified
-# details of the native text format, but the default SystemFlavorMap will
-# present a large set of synthesized DataFlavors which map, in both
-# directions, to the native. After receiving data from the application in one
-# of the synthetic DataFlavors, the data transfer subsystem will transform
-# the data stream into the format specified in this file before passing the
-# transformed stream to the native system.
-#
-# Mappings whose values specify DataFlavors with primary MIME types of
-# "text", but which do not support the charset parameter, will be treated as
-# opaque, 8-bit data. They will not undergo any transformation process, and
-# any "charset", "eoln", or "terminators" parameters specified in this file
-# will be ignored.
-#
-# See java.awt.datatransfer.DataFlavor.selectBestTextFlavor for a list of
-# text flavors which support the charset parameter.
-
-UNICODE\ TEXT=text/plain;charset=utf-16le;eoln="\r\n";terminators=2
-TEXT=text/plain;eoln="\r\n";terminators=1
-HTML\ Format=text/html;charset=utf-8;eoln="\r\n";terminators=1
-Rich\ Text\ Format=text/rtf
-HDROP=application/x-java-file-list;class=java.util.List
-PNG=image/x-java-image;class=java.awt.Image
-JFIF=image/x-java-image;class=java.awt.Image
-DIB=image/x-java-image;class=java.awt.Image
-ENHMETAFILE=image/x-java-image;class=java.awt.Image
-METAFILEPICT=image/x-java-image;class=java.awt.Image
-LOCALE=application/x-java-text-encoding;class="[B"
-UniformResourceLocator=application/x-java-url;class=java.net.URL,\
- text/uri-list;eoln="\r\n";terminators=1,\
- text/plain;eoln="\r\n";terminators=1
-FileGroupDescriptorW=application/x-java-file-list;class=java.util.List
-FileGroupDescriptor=application/x-java-file-list;class=java.util.List
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WBufferStrategy.java Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.awt.windows;
-
-import java.awt.Image;
-import java.awt.Component;
-
-/**
- * This sun-private class exists solely to get a handle to
- * the back buffer associated with a Component. If that
- * Component has a BufferStrategy with >1 buffer, then the
- * Image subclass associated with that buffer will be returned.
- * Note: the class is used by the JAWT3d.
- */
-public final class WBufferStrategy {
-
- private static native void initIDs(Class <?> componentClass);
-
- static {
- initIDs(Component.class);
- }
-
- public static native Image getDrawBuffer(Component comp);
-
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/windows/classes/sun/datatransfer/resources/flavormap.properties Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,69 @@
+#
+# This properties file is used to initialize the default
+# java.awt.datatransfer.SystemFlavorMap. It contains the Win32 platform-
+# specific, default mappings between common Win32 Clipboard atoms and platform-
+# independent MIME type strings, which will be converted into
+# java.awt.datatransfer.DataFlavors.
+#
+# The standard format is:
+#
+# <native>=<MIME type>,<MIME type>, ...
+#
+# <native> should be a string identifier that the native platform will
+# recognize as a valid data format. <MIME type> should specify both a MIME
+# primary type and a MIME subtype separated by a '/'. The MIME type may include
+# parameters, where each parameter is a key/value pair separated by '=', and
+# where each parameter to the MIME type is separated by a ';'.
+#
+# Because SystemFlavorMap implements FlavorTable, developers are free to
+# duplicate DataFlavor values and set multiple values for a single native by
+# separating them with ",". If a mapping contains a duplicate key or value,
+# earlier mappings which included this key or value will be preferred.#
+# Mappings whose values specify DataFlavors with primary MIME types of
+# "text", and which support the charset parameter, should specify the exact
+# format in which the native platform expects the data. The "charset"
+# parameter specifies the char to byte encoding, the "eoln" parameter
+# specifies the end-of-line marker, and the "terminators" parameter specifies
+# the number of terminating NUL bytes. Note that "eoln" and "terminators"
+# are not standardized MIME type parameters. They are specific to this file
+# format ONLY. They will not appear in any of the DataFlavors returned by the
+# SystemFlavorMap at the Java level.
+#
+# If the "charset" parameter is omitted, or has zero length, the platform
+# default encoding is assumed. If the "eoln" parameter is omitted, or has
+# zero length, "\n" is assumed. If the "terminators" parameter is omitted,
+# or has a value less than zero, zero is assumed.
+#
+# Upon initialization, the data transfer subsystem will record the specified
+# details of the native text format, but the default SystemFlavorMap will
+# present a large set of synthesized DataFlavors which map, in both
+# directions, to the native. After receiving data from the application in one
+# of the synthetic DataFlavors, the data transfer subsystem will transform
+# the data stream into the format specified in this file before passing the
+# transformed stream to the native system.
+#
+# Mappings whose values specify DataFlavors with primary MIME types of
+# "text", but which do not support the charset parameter, will be treated as
+# opaque, 8-bit data. They will not undergo any transformation process, and
+# any "charset", "eoln", or "terminators" parameters specified in this file
+# will be ignored.
+#
+# See java.awt.datatransfer.DataFlavor.selectBestTextFlavor for a list of
+# text flavors which support the charset parameter.
+
+UNICODE\ TEXT=text/plain;charset=utf-16le;eoln="\r\n";terminators=2
+TEXT=text/plain;eoln="\r\n";terminators=1
+HTML\ Format=text/html;charset=utf-8;eoln="\r\n";terminators=1
+Rich\ Text\ Format=text/rtf
+HDROP=application/x-java-file-list;class=java.util.List
+PNG=image/x-java-image;class=java.awt.Image
+JFIF=image/x-java-image;class=java.awt.Image
+DIB=image/x-java-image;class=java.awt.Image
+ENHMETAFILE=image/x-java-image;class=java.awt.Image
+METAFILEPICT=image/x-java-image;class=java.awt.Image
+LOCALE=application/x-java-text-encoding;class="[B"
+UniformResourceLocator=application/x-java-url;class=java.net.URL,\
+ text/uri-list;eoln="\r\n";terminators=1,\
+ text/plain;eoln="\r\n";terminators=1
+FileGroupDescriptorW=application/x-java-file-list;class=java.util.List
+FileGroupDescriptor=application/x-java-file-list;class=java.util.List
--- a/jdk/src/java.desktop/windows/native/libawt/sun/java2d/d3d/D3DPipeline.cpp Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, 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.
- */
-
-#include "D3DPipeline.h"
-
-BOOL APIENTRY DllMain( HANDLE hModule,
- DWORD ul_reason_for_call,
- LPVOID lpReserved)
-{
- switch (ul_reason_for_call) {
- case DLL_PROCESS_ATTACH:
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- case DLL_PROCESS_DETACH:
- break;
- }
- return TRUE;
-}
--- a/jdk/src/java.desktop/windows/native/libawt/sun/windows/WBufferStrategy.cpp Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2002, 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.
- */
-
-#include "sun_awt_windows_WBufferStrategy.h"
-#include "jni_util.h"
-
-
-static jmethodID getBackBufferID;
-
-/*
- * Class: sun_awt_windows_WBufferStrategy
- * Method: initIDs
- * Signature: (Ljava/lang/Class;)V
- */
-JNIEXPORT void JNICALL
-Java_sun_awt_windows_WBufferStrategy_initIDs(JNIEnv *env, jclass wbs,
- jclass componentClass)
-{
- getBackBufferID = env->GetMethodID(componentClass, "getBackBuffer",
- "()Ljava/awt/Image;");
-}
-
-/**
- * Native method of WBufferStrategy.java. Given a Component
- * object, this method will find the back buffer associated
- * with the Component's BufferStrategy and return a handle
- * to it.
- */
-extern "C" JNIEXPORT jobject JNICALL
-Java_sun_awt_windows_WBufferStrategy_getDrawBuffer(JNIEnv *env, jclass wbs,
- jobject component)
-{
- if (!JNU_IsNull(env, getBackBufferID)) {
- return env->CallObjectMethod(component, getBackBufferID);
- } else {
- return NULL;
- }
-}
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnector.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnector.java Wed Jul 05 20:01:44 2017 +0200
@@ -1335,66 +1335,94 @@
int maxNotifications,
long timeout)
throws IOException, ClassNotFoundException {
- IOException org;
+ boolean retried = false;
while (true) { // used for a successful re-connection
+ // or a transient network problem
try {
return connection.fetchNotifications(clientSequenceNumber,
maxNotifications,
- timeout);
+ timeout); // return normally
} catch (IOException ioe) {
- org = ioe;
+ // Examine the chain of exceptions to determine whether this
+ // is a deserialization issue. If so - we propagate the
+ // appropriate exception to the caller, who will then
+ // proceed with fetching notifications one by one
+ rethrowDeserializationException(ioe);
- // inform of IOException
try {
communicatorAdmin.gotIOException(ioe);
-
- // The connection should be re-established.
- continue;
+ // reconnection OK, back to "while" to do again
} catch (IOException ee) {
- // No more fetch, the Exception will be re-thrown.
- break;
- } // never reached
- } // never reached
- }
+ boolean toClose = false;
- // specially treating for an UnmarshalException
- if (org instanceof UnmarshalException) {
- UnmarshalException ume = (UnmarshalException)org;
-
- if (ume.detail instanceof ClassNotFoundException)
- throw (ClassNotFoundException) ume.detail;
+ synchronized (this) {
+ if (terminated) {
+ // the connection is closed.
+ throw ioe;
+ } else if (retried) {
+ toClose = true;
+ }
+ }
- /* In Sun's RMI implementation, if a method return
- contains an unserializable object, then we get
- UnmarshalException wrapping WriteAbortedException
- wrapping NotSerializableException. In that case we
- extract the NotSerializableException so that our
- caller can realize it should try to skip past the
- notification that presumably caused it. It's not
- certain that every other RMI implementation will
- generate this exact exception sequence. If not, we
- will not detect that the problem is due to an
- unserializable object, and we will stop trying to
- receive notifications from the server. It's not
- clear we can do much better. */
- if (ume.detail instanceof WriteAbortedException) {
- WriteAbortedException wae =
- (WriteAbortedException) ume.detail;
- if (wae.detail instanceof IOException)
- throw (IOException) wae.detail;
+ if (toClose) {
+ // JDK-8049303
+ // We received an IOException - but the communicatorAdmin
+ // did not close the connection - possibly because
+ // the original exception was raised by a transient network
+ // problem?
+ // We already know that this exception is not due to a deserialization
+ // issue as we already took care of that before involving the
+ // communicatorAdmin. Moreover - we already made one retry attempt
+ // at fetching the same batch of notifications - and the
+ // problem persisted.
+ // Since trying again doesn't seem to solve the issue, we will now
+ // close the connection. Doing otherwise might cause the
+ // NotifFetcher thread to die silently.
+ final Notification failedNotif =
+ new JMXConnectionNotification(
+ JMXConnectionNotification.FAILED,
+ this,
+ connectionId,
+ clientNotifSeqNo++,
+ "Failed to communicate with the server: " + ioe.toString(),
+ ioe);
+
+ sendNotification(failedNotif);
+
+ try {
+ close(true);
+ } catch (Exception e) {
+ // OK.
+ // We are closing
+ }
+ throw ioe; // the connection is closed here.
+ } else {
+ // JDK-8049303 possible transient network problem,
+ // let's try one more time
+ retried = true;
+ }
+ }
}
- } else if (org instanceof MarshalException) {
+ }
+ }
+
+ private void rethrowDeserializationException(IOException ioe)
+ throws ClassNotFoundException, IOException {
+ // specially treating for an UnmarshalException
+ if (ioe instanceof UnmarshalException) {
+ throw ioe; // the fix of 6937053 made ClientNotifForwarder.fetchNotifs
+ // fetch one by one with UnmarshalException
+ } else if (ioe instanceof MarshalException) {
// IIOP will throw MarshalException wrapping a NotSerializableException
// when a server fails to serialize a response.
- MarshalException me = (MarshalException)org;
+ MarshalException me = (MarshalException)ioe;
if (me.detail instanceof NotSerializableException) {
throw (NotSerializableException)me.detail;
}
}
- // Not serialization problem, simply re-throw the orginal exception
- throw org;
+ // Not serialization problem, return.
}
protected Integer addListenerForMBeanRemovedNotif()
--- a/jdk/src/java.security.jgss/share/classes/com/sun/security/jgss/AuthorizationDataEntry.java Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.security.jgss;
-
-/**
- * Kerberos 5 AuthorizationData entry.
- */
-@jdk.Exported
-public final class AuthorizationDataEntry {
-
- private final int type;
- private final byte[] data;
-
- /**
- * Create an AuthorizationDataEntry object.
- * @param type the ad-type
- * @param data the ad-data, a copy of the data will be saved
- * inside the object.
- */
- public AuthorizationDataEntry(int type, byte[] data) {
- this.type = type;
- this.data = data.clone();
- }
-
- /**
- * Get the ad-type field.
- * @return ad-type
- */
- public int getType() {
- return type;
- }
-
- /**
- * Get a copy of the ad-data field.
- * @return ad-data
- */
- public byte[] getData() {
- return data.clone();
- }
-
- public String toString() {
- return "AuthorizationDataEntry: type="+type+", data=" +
- data.length + " bytes:\n" +
- new sun.misc.HexDumpEncoder().encodeBuffer(data);
- }
-}
--- a/jdk/src/java.security.jgss/share/classes/com/sun/security/jgss/ExtendedGSSContext.java Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.security.jgss;
-
-import org.ietf.jgss.*;
-
-/**
- * The extended GSSContext interface for supporting additional
- * functionalities not defined by {@code org.ietf.jgss.GSSContext},
- * such as querying context-specific attributes.
- */
-@jdk.Exported
-public interface ExtendedGSSContext extends GSSContext {
- /**
- * Return the mechanism-specific attribute associated with {@code type}.
- * <p>
- * If there is a security manager, an {@link InquireSecContextPermission}
- * with the name {@code type.mech} must be granted. Otherwise, this could
- * result in a {@link SecurityException}.<p>
- *
- * Example:
- * <pre>
- * GSSContext ctxt = m.createContext(...)
- * // Establishing the context
- * if (ctxt instanceof ExtendedGSSContext) {
- * ExtendedGSSContext ex = (ExtendedGSSContext)ctxt;
- * try {
- * Key key = (key)ex.inquireSecContext(
- * InquireType.KRB5_GET_SESSION_KEY);
- * // read key info
- * } catch (GSSException gsse) {
- * // deal with exception
- * }
- * }
- * </pre>
- * @param type the type of the attribute requested
- * @return the attribute, see the method documentation for details.
- * @throws GSSException containing the following
- * major error codes:
- * {@link GSSException#BAD_MECH GSSException.BAD_MECH} if the mechanism
- * does not support this method,
- * {@link GSSException#UNAVAILABLE GSSException.UNAVAILABLE} if the
- * type specified is not supported,
- * {@link GSSException#NO_CONTEXT GSSException.NO_CONTEXT} if the
- * security context is invalid,
- * {@link GSSException#FAILURE GSSException.FAILURE} for other
- * unspecified failures.
- * @throws SecurityException if a security manager exists and a proper
- * {@link InquireSecContextPermission} is not granted.
- * @see InquireSecContextPermission
- * @see InquireType
- */
- public Object inquireSecContext(InquireType type)
- throws GSSException;
-
- /**
- * Requests that the delegation policy be respected. When a true value is
- * requested, the underlying context would use the delegation policy
- * defined by the environment as a hint to determine whether credentials
- * delegation should be performed. This request can only be made on the
- * context initiator's side and it has to be done prior to the first
- * call to <code>initSecContext</code>.
- * <p>
- * When this flag is false, delegation will only be tried when the
- * {@link GSSContext#requestCredDeleg(boolean) credentials delegation flag}
- * is true.
- * <p>
- * When this flag is true but the
- * {@link GSSContext#requestCredDeleg(boolean) credentials delegation flag}
- * is false, delegation will be only tried if the delegation policy permits
- * delegation.
- * <p>
- * When both this flag and the
- * {@link GSSContext#requestCredDeleg(boolean) credentials delegation flag}
- * are true, delegation will be always tried. However, if the delegation
- * policy does not permit delegation, the value of
- * {@link #getDelegPolicyState} will be false, even
- * if delegation is performed successfully.
- * <p>
- * In any case, if the delegation is not successful, the value returned
- * by {@link GSSContext#getCredDelegState()} is false, and the value
- * returned by {@link #getDelegPolicyState()} is also false.
- * <p>
- * Not all mechanisms support delegation policy. Therefore, the
- * application should check to see if the request was honored with the
- * {@link #getDelegPolicyState() getDelegPolicyState} method. When
- * delegation policy is not supported, <code>requestDelegPolicy</code>
- * should return silently without throwing an exception.
- * <p>
- * Note: for the Kerberos 5 mechanism, the delegation policy is expressed
- * through the OK-AS-DELEGATE flag in the service ticket. When it's true,
- * the KDC permits delegation to the target server. In a cross-realm
- * environment, in order for delegation be permitted, all cross-realm TGTs
- * on the authentication path must also have the OK-AS-DELAGATE flags set.
- * @param state true if the policy should be respected
- * @throws GSSException containing the following
- * major error codes:
- * {@link GSSException#FAILURE GSSException.FAILURE}
- */
- public void requestDelegPolicy(boolean state) throws GSSException;
-
- /**
- * Returns the delegation policy response. Called after a security context
- * is established. This method can be only called on the initiator's side.
- * See {@link ExtendedGSSContext#requestDelegPolicy}.
- * @return the delegation policy response
- */
- public boolean getDelegPolicyState();
-}
--- a/jdk/src/java.security.jgss/share/classes/com/sun/security/jgss/ExtendedGSSCredential.java Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.security.jgss;
-
-import org.ietf.jgss.*;
-
-/**
- * The extended GSSCredential interface for supporting additional
- * functionalities not defined by {@code org.ietf.jgss.GSSCredential}.
- * @since 1.8
- */
-@jdk.Exported
-public interface ExtendedGSSCredential extends GSSCredential {
- /**
- * Impersonates a principal. In Kerberos, this can be implemented
- * using the Microsoft S4U2self extension.
- * <p>
- * A {@link GSSException#NO_CRED GSSException.NO_CRED} will be thrown if the
- * impersonation fails. A {@link GSSException#FAILURE GSSException.FAILURE}
- * will be thrown if the impersonation method is not available to this
- * credential object.
- * @param name the name of the principal to impersonate
- * @return a credential for that principal
- * @throws GSSException containing the following
- * major error codes:
- * {@link GSSException#NO_CRED GSSException.NO_CRED}
- * {@link GSSException#FAILURE GSSException.FAILURE}
- */
- public GSSCredential impersonate(GSSName name) throws GSSException;
-}
--- a/jdk/src/java.security.jgss/share/classes/com/sun/security/jgss/GSSUtil.java Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.security.jgss;
-
-import javax.security.auth.Subject;
-import org.ietf.jgss.GSSName;
-import org.ietf.jgss.GSSCredential;
-
-/**
- * GSS-API Utilities for using in conjunction with Sun Microsystem's
- * implementation of Java GSS-API.
- */
-@jdk.Exported
-public class GSSUtil {
-
- /**
- * Use this method to convert a GSSName and GSSCredential into a
- * Subject. Typically this would be done by a server that wants to
- * impersonate a client thread at the Java level by setting a client
- * Subject in the current access control context. If the server is merely
- * interested in using a principal based policy in its local JVM, then
- * it only needs to provide the GSSName of the client.
- *
- * The elements from the GSSName are placed in the principals set of this
- * Subject and those from the GSSCredential are placed in the private
- * credentials set of the Subject. Any Kerberos specific elements that
- * are added to the subject will be instances of the standard Kerberos
- * implementation classes defined in javax.security.auth.kerberos.
- *
- * @return a Subject with the entries that contain elements from the
- * given GSSName and GSSCredential.
- *
- * @param principals a GSSName containing one or more mechanism specific
- * representations of the same entity. These mechanism specific
- * representations will be populated in the returned Subject's principal
- * set.
- *
- * @param credentials a GSSCredential containing one or more mechanism
- * specific credentials for the same entity. These mechanism specific
- * credentials will be populated in the returned Subject's private
- * credential set. Passing in a value of null will imply that the private
- * credential set should be left empty.
- */
- public static Subject createSubject(GSSName principals,
- GSSCredential credentials) {
-
- return sun.security.jgss.GSSUtil.getSubject(principals,
- credentials);
- }
-}
--- a/jdk/src/java.security.jgss/share/classes/com/sun/security/jgss/InquireSecContextPermission.java Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.security.jgss;
-
-import java.security.BasicPermission;
-
-/**
- * This class is used to protect various attributes of an established
- * GSS security context that can be accessed using the
- * {@link com.sun.security.jgss.ExtendedGSSContext#inquireSecContext}
- * method.
- *
- * <p>The target name is the {@link InquireType} allowed.
- */
-@jdk.Exported
-public final class InquireSecContextPermission extends BasicPermission {
- private static final long serialVersionUID = -7131173349668647297L;
-
- /**
- * Constructs a new {@code InquireSecContextPermission} object with
- * the specified name. The name is the symbolic name of the
- * {@link InquireType} allowed.
- *
- * @param name the {@link InquireType} allowed by this
- * permission. "*" means all {@link InquireType}s are allowed.
- *
- * @throws NullPointerException if <code>name</code> is <code>null</code>.
- * @throws IllegalArgumentException if <code>name</code> is empty.
- */
- public InquireSecContextPermission(String name) {
- super(name);
- }
-}
--- a/jdk/src/java.security.jgss/share/classes/com/sun/security/jgss/InquireType.java Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.security.jgss;
-
-/**
- * Attribute types that can be specified as an argument of
- * {@link com.sun.security.jgss.ExtendedGSSContext#inquireSecContext}
- */
-@jdk.Exported
-public enum InquireType {
- /**
- * Attribute type for retrieving the session key of an established
- * Kerberos 5 security context. The returned object is an instance of
- * {@link java.security.Key}, which has the following properties:
- * <ul>
- * <li>Algorithm: enctype as a string, where
- * enctype is defined in RFC 3961, section 8.
- * <li>Format: "RAW"
- * <li>Encoded form: the raw key bytes, not in any ASN.1 encoding
- * </ul>
- * @deprecated as of 1.9, replaced by {@link #KRB5_GET_SESSION_KEY_EX}
- * which returns an instance of
- * {@link javax.security.auth.kerberos.EncryptionKey}
- * that implements the {@link javax.crypto.SecretKey} interface and
- * has similar methods with {@link javax.security.auth.kerberos.KerberosKey}.
- */
- @Deprecated
- KRB5_GET_SESSION_KEY,
- /**
- * Attribute type for retrieving the session key of an
- * established Kerberos 5 security context. The return value is an
- * instance of {@link javax.security.auth.kerberos.EncryptionKey}.
- *
- * @since 1.9
- */
- KRB5_GET_SESSION_KEY_EX,
- /**
- * Attribute type for retrieving the service ticket flags of an
- * established Kerberos 5 security context. The returned object is
- * a boolean array for the service ticket flags, which is long enough
- * to contain all true bits. This means if the user wants to get the
- * <em>n</em>'th bit but the length of the returned array is less than
- * <em>n</em>, it is regarded as false.
- */
- KRB5_GET_TKT_FLAGS,
- /**
- * Attribute type for retrieving the authorization data in the
- * service ticket of an established Kerberos 5 security context.
- * Only supported on the acceptor side.
- */
- KRB5_GET_AUTHZ_DATA,
- /**
- * Attribute type for retrieving the authtime in the service ticket
- * of an established Kerberos 5 security context. The returned object
- * is a String object in the standard KerberosTime format defined in
- * RFC 4120 Section 5.2.3.
- */
- KRB5_GET_AUTHTIME,
- /**
- * Attribute type for retrieving the KRB_CRED message that an initiator
- * is about to send to an acceptor. The return type is an instance of
- * {@link javax.security.auth.kerberos.KerberosCredMessage}.
- *
- * @since 1.9
- */
- KRB5_GET_KRB_CRED,
-}
--- a/jdk/src/java.security.jgss/share/classes/com/sun/security/jgss/package-info.java Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-@jdk.Exported
-package com.sun.security.jgss;
--- a/jdk/src/java.security.jgss/share/classes/com/sun/security/sasl/gsskerb/FactoryImpl.java Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.security.sasl.gsskerb;
-
-import javax.security.sasl.*;
-import com.sun.security.sasl.util.PolicyUtils;
-
-import java.util.Map;
-import javax.security.auth.callback.CallbackHandler;
-
-/**
- * Client/server factory for GSSAPI (Kerberos V5) SASL client/server mechs.
- * See GssKrb5Client/GssKrb5Server for input requirements.
- *
- * @author Rosanna Lee
- */
-public final class FactoryImpl implements SaslClientFactory, SaslServerFactory {
- private static final String myMechs[] = {
- "GSSAPI"};
-
- private static final int mechPolicies[] = {
- PolicyUtils.NOPLAINTEXT|PolicyUtils.NOANONYMOUS|PolicyUtils.NOACTIVE
- };
-
- private static final int GSS_KERB_V5 = 0;
-
- public FactoryImpl() {
- }
-
- public SaslClient createSaslClient(String[] mechs,
- String authorizationId,
- String protocol,
- String serverName,
- Map<String,?> props,
- CallbackHandler cbh) throws SaslException {
-
- for (int i = 0; i < mechs.length; i++) {
- if (mechs[i].equals(myMechs[GSS_KERB_V5])
- && PolicyUtils.checkPolicy(mechPolicies[GSS_KERB_V5], props)) {
- return new GssKrb5Client(
- authorizationId,
- protocol,
- serverName,
- props,
- cbh);
- }
- }
- return null;
- };
-
- public SaslServer createSaslServer(String mech,
- String protocol,
- String serverName,
- Map<String,?> props,
- CallbackHandler cbh) throws SaslException {
- if (mech.equals(myMechs[GSS_KERB_V5])
- && PolicyUtils.checkPolicy(mechPolicies[GSS_KERB_V5], props)) {
- if (cbh == null) {
- throw new SaslException(
- "Callback handler with support for AuthorizeCallback required");
- }
- return new GssKrb5Server(
- protocol,
- serverName,
- props,
- cbh);
- }
- return null;
- };
-
- public String[] getMechanismNames(Map<String,?> props) {
- return PolicyUtils.filterMechs(myMechs, mechPolicies, props);
- }
-}
--- a/jdk/src/java.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Base.java Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package com.sun.security.sasl.gsskerb;
-
-import java.util.Locale;
-import java.util.Map;
-import java.util.logging.Level;
-import javax.security.sasl.*;
-import com.sun.security.sasl.util.AbstractSaslImpl;
-import org.ietf.jgss.*;
-import com.sun.security.jgss.ExtendedGSSContext;
-import com.sun.security.jgss.InquireType;
-
-abstract class GssKrb5Base extends AbstractSaslImpl {
-
- private static final String KRB5_OID_STR = "1.2.840.113554.1.2.2";
- protected static Oid KRB5_OID;
- protected static final byte[] EMPTY = new byte[0];
-
- static {
- try {
- KRB5_OID = new Oid(KRB5_OID_STR);
- } catch (GSSException ignore) {}
- }
-
- protected GSSContext secCtx = null;
- protected static final int JGSS_QOP = 0; // unrelated to SASL QOP mask
-
- protected GssKrb5Base(Map<String, ?> props, String className)
- throws SaslException {
- super(props, className);
- }
-
- /**
- * Retrieves this mechanism's name.
- *
- * @return The string "GSSAPI".
- */
- public String getMechanismName() {
- return "GSSAPI";
- }
-
- @Override
- public Object getNegotiatedProperty(String propName) {
- if (!completed) {
- throw new IllegalStateException("Authentication incomplete");
- }
- String xprefix = "com.sun.security.jgss.inquiretype.";
- if (propName.startsWith(xprefix)) {
- String type = propName.substring(xprefix.length());
- if (logger.isLoggable(Level.FINEST)) {
- logger.logp(Level.FINE, "GssKrb5Base",
- "getNegotiatedProperty", propName);
- }
- for (InquireType t: InquireType.values()) {
- if (t.name().toLowerCase(Locale.US).equals(type)) {
- try {
- return ((ExtendedGSSContext)secCtx).inquireSecContext(t);
- } catch (GSSException e) {
- if (logger.isLoggable(Level.FINEST)) {
- logger.log(Level.WARNING, "inquireSecContext error", e);
- }
- return null;
- }
- }
- }
- // No such InquireType. Although not likely to be defined
- // as a property in a parent class, still try it.
- }
- return super.getNegotiatedProperty(propName);
- }
-
- public byte[] unwrap(byte[] incoming, int start, int len)
- throws SaslException {
- if (!completed) {
- throw new IllegalStateException("GSSAPI authentication not completed");
- }
-
- // integrity will be true if either privacy or integrity negotiated
- if (!integrity) {
- throw new IllegalStateException("No security layer negotiated");
- }
-
- try {
- MessageProp msgProp = new MessageProp(JGSS_QOP, privacy);
- byte[] answer = secCtx.unwrap(incoming, start, len, msgProp);
- if (logger.isLoggable(Level.FINEST)) {
- traceOutput(myClassName, "KRB501:Unwrap", "incoming: ",
- incoming, start, len);
- traceOutput(myClassName, "KRB502:Unwrap", "unwrapped: ",
- answer, 0, answer.length);
- }
- return answer;
- } catch (GSSException e) {
- throw new SaslException("Problems unwrapping SASL buffer", e);
- }
- }
-
- public byte[] wrap(byte[] outgoing, int start, int len) throws SaslException {
- if (!completed) {
- throw new IllegalStateException("GSSAPI authentication not completed");
- }
-
- // integrity will be true if either privacy or integrity negotiated
- if (!integrity) {
- throw new IllegalStateException("No security layer negotiated");
- }
-
- // Generate GSS token
- try {
- MessageProp msgProp = new MessageProp(JGSS_QOP, privacy);
- byte[] answer = secCtx.wrap(outgoing, start, len, msgProp);
- if (logger.isLoggable(Level.FINEST)) {
- traceOutput(myClassName, "KRB503:Wrap", "outgoing: ",
- outgoing, start, len);
- traceOutput(myClassName, "KRB504:Wrap", "wrapped: ",
- answer, 0, answer.length);
- }
- return answer;
-
- } catch (GSSException e) {
- throw new SaslException("Problem performing GSS wrap", e);
- }
- }
-
- public void dispose() throws SaslException {
- if (secCtx != null) {
- try {
- secCtx.dispose();
- } catch (GSSException e) {
- throw new SaslException("Problem disposing GSS context", e);
- }
- secCtx = null;
- }
- }
-
- protected void finalize() throws Throwable {
- dispose();
- }
-}
--- a/jdk/src/java.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Client.java Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,329 +0,0 @@
-/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.security.sasl.gsskerb;
-
-import java.io.IOException;
-import java.util.Map;
-import java.util.logging.Level;
-import javax.security.sasl.*;
-
-// JAAS
-import javax.security.auth.callback.CallbackHandler;
-
-// JGSS
-import org.ietf.jgss.*;
-
-/**
- * Implements the GSSAPI SASL client mechanism for Kerberos V5.
- * (<A HREF="http://www.ietf.org/rfc/rfc2222.txt">RFC 2222</A>,
- * <a HREF="http://www.ietf.org/internet-drafts/draft-ietf-cat-sasl-gssapi-04.txt">draft-ietf-cat-sasl-gssapi-04.txt</a>).
- * It uses the Java Bindings for GSSAPI
- * (<A HREF="http://www.ietf.org/rfc/rfc2853.txt">RFC 2853</A>)
- * for getting GSSAPI/Kerberos V5 support.
- *
- * The client/server interactions are:
- * C0: bind (GSSAPI, initial response)
- * S0: sasl-bind-in-progress, challenge 1 (output of accept_sec_context or [])
- * C1: bind (GSSAPI, response 1 (output of init_sec_context or []))
- * S1: sasl-bind-in-progress challenge 2 (security layer, server max recv size)
- * C2: bind (GSSAPI, response 2 (security layer, client max recv size, authzid))
- * S2: bind success response
- *
- * Expects the client's credentials to be supplied from the
- * javax.security.sasl.credentials property or from the thread's Subject.
- * Otherwise the underlying KRB5 mech will attempt to acquire Kerberos creds
- * by logging into Kerberos (via default TextCallbackHandler).
- * These creds will be used for exchange with server.
- *
- * Required callbacks: none.
- *
- * Environment properties that affect behavior of implementation:
- *
- * javax.security.sasl.qop
- * - quality of protection; list of auth, auth-int, auth-conf; default is "auth"
- * javax.security.sasl.maxbuf
- * - max receive buffer size; default is 65536
- * javax.security.sasl.sendmaxbuffer
- * - max send buffer size; default is 65536; (min with server max recv size)
- *
- * javax.security.sasl.server.authentication
- * - "true" means require mutual authentication; default is "false"
- *
- * javax.security.sasl.credentials
- * - an {@link org.ietf.jgss.GSSCredential} used for delegated authentication.
- *
- * @author Rosanna Lee
- */
-
-final class GssKrb5Client extends GssKrb5Base implements SaslClient {
- // ---------------- Constants -----------------
- private static final String MY_CLASS_NAME = GssKrb5Client.class.getName();
-
- private boolean finalHandshake = false;
- private boolean mutual = false; // default false
- private byte[] authzID;
-
- /**
- * Creates a SASL mechanism with client credentials that it needs
- * to participate in GSS-API/Kerberos v5 authentication exchange
- * with the server.
- */
- GssKrb5Client(String authzID, String protocol, String serverName,
- Map<String, ?> props, CallbackHandler cbh) throws SaslException {
-
- super(props, MY_CLASS_NAME);
-
- String service = protocol + "@" + serverName;
- logger.log(Level.FINE, "KRB5CLNT01:Requesting service name: {0}",
- service);
-
- try {
- GSSManager mgr = GSSManager.getInstance();
-
- // Create the name for the requested service entity for Krb5 mech
- GSSName acceptorName = mgr.createName(service,
- GSSName.NT_HOSTBASED_SERVICE, KRB5_OID);
-
- // Parse properties to check for supplied credentials
- GSSCredential credentials = null;
- if (props != null) {
- Object prop = props.get(Sasl.CREDENTIALS);
- if (prop != null && prop instanceof GSSCredential) {
- credentials = (GSSCredential) prop;
- logger.log(Level.FINE,
- "KRB5CLNT01:Using the credentials supplied in " +
- "javax.security.sasl.credentials");
- }
- }
-
- // Create a context using credentials for Krb5 mech
- secCtx = mgr.createContext(acceptorName,
- KRB5_OID, /* mechanism */
- credentials, /* credentials */
- GSSContext.INDEFINITE_LIFETIME);
-
- // Request credential delegation when credentials have been supplied
- if (credentials != null) {
- secCtx.requestCredDeleg(true);
- }
-
- // Parse properties to set desired context options
- if (props != null) {
- // Mutual authentication
- String prop = (String)props.get(Sasl.SERVER_AUTH);
- if (prop != null) {
- mutual = "true".equalsIgnoreCase(prop);
- }
- }
- secCtx.requestMutualAuth(mutual);
-
- // Always specify potential need for integrity and confidentiality
- // Decision will be made during final handshake
- secCtx.requestConf(true);
- secCtx.requestInteg(true);
-
- } catch (GSSException e) {
- throw new SaslException("Failure to initialize security context", e);
- }
-
- if (authzID != null && authzID.length() > 0) {
- try {
- this.authzID = authzID.getBytes("UTF8");
- } catch (IOException e) {
- throw new SaslException("Cannot encode authorization ID", e);
- }
- }
- }
-
- public boolean hasInitialResponse() {
- return true;
- }
-
- /**
- * Processes the challenge data.
- *
- * The server sends a challenge data using which the client must
- * process using GSS_Init_sec_context.
- * As per RFC 2222, when GSS_S_COMPLETE is returned, we do
- * an extra handshake to determine the negotiated security protection
- * and buffer sizes.
- *
- * @param challengeData A non-null byte array containing the
- * challenge data from the server.
- * @return A non-null byte array containing the response to be
- * sent to the server.
- */
- public byte[] evaluateChallenge(byte[] challengeData) throws SaslException {
- if (completed) {
- throw new IllegalStateException(
- "GSSAPI authentication already complete");
- }
-
- if (finalHandshake) {
- return doFinalHandshake(challengeData);
- } else {
-
- // Security context not established yet; continue with init
-
- try {
- byte[] gssOutToken = secCtx.initSecContext(challengeData,
- 0, challengeData.length);
- if (logger.isLoggable(Level.FINER)) {
- traceOutput(MY_CLASS_NAME, "evaluteChallenge",
- "KRB5CLNT02:Challenge: [raw]", challengeData);
- traceOutput(MY_CLASS_NAME, "evaluateChallenge",
- "KRB5CLNT03:Response: [after initSecCtx]", gssOutToken);
- }
-
- if (secCtx.isEstablished()) {
- finalHandshake = true;
- if (gssOutToken == null) {
- // RFC 2222 7.2.1: Client responds with no data
- return EMPTY;
- }
- }
-
- return gssOutToken;
- } catch (GSSException e) {
- throw new SaslException("GSS initiate failed", e);
- }
- }
- }
-
- private byte[] doFinalHandshake(byte[] challengeData) throws SaslException {
- try {
- // Security context already established. challengeData
- // should contain security layers and server's maximum buffer size
-
- if (logger.isLoggable(Level.FINER)) {
- traceOutput(MY_CLASS_NAME, "doFinalHandshake",
- "KRB5CLNT04:Challenge [raw]:", challengeData);
- }
-
- if (challengeData.length == 0) {
- // Received S0, should return []
- return EMPTY;
- }
-
- // Received S1 (security layer, server max recv size)
-
- byte[] gssOutToken = secCtx.unwrap(challengeData, 0,
- challengeData.length, new MessageProp(0, false));
-
- // First octet is a bit-mask specifying the protections
- // supported by the server
- if (logger.isLoggable(Level.FINE)) {
- if (logger.isLoggable(Level.FINER)) {
- traceOutput(MY_CLASS_NAME, "doFinalHandshake",
- "KRB5CLNT05:Challenge [unwrapped]:", gssOutToken);
- }
- logger.log(Level.FINE, "KRB5CLNT06:Server protections: {0}",
- gssOutToken[0]);
- }
-
- // Client selects preferred protection
- // qop is ordered list of qop values
- byte selectedQop = findPreferredMask(gssOutToken[0], qop);
- if (selectedQop == 0) {
- throw new SaslException(
- "No common protection layer between client and server");
- }
-
- if ((selectedQop&PRIVACY_PROTECTION) != 0) {
- privacy = true;
- integrity = true;
- } else if ((selectedQop&INTEGRITY_ONLY_PROTECTION) != 0) {
- integrity = true;
- }
-
- // 2nd-4th octets specifies maximum buffer size expected by
- // server (in network byte order)
- int srvMaxBufSize = networkByteOrderToInt(gssOutToken, 1, 3);
-
- // Determine the max send buffer size based on what the
- // server is able to receive and our specified max
- sendMaxBufSize = (sendMaxBufSize == 0) ? srvMaxBufSize :
- Math.min(sendMaxBufSize, srvMaxBufSize);
-
- // Update context to limit size of returned buffer
- rawSendSize = secCtx.getWrapSizeLimit(JGSS_QOP, privacy,
- sendMaxBufSize);
-
- if (logger.isLoggable(Level.FINE)) {
- logger.log(Level.FINE,
-"KRB5CLNT07:Client max recv size: {0}; server max recv size: {1}; rawSendSize: {2}",
- new Object[] {recvMaxBufSize,
- srvMaxBufSize,
- rawSendSize});
- }
-
- // Construct negotiated security layers and client's max
- // receive buffer size and authzID
- int len = 4;
- if (authzID != null) {
- len += authzID.length;
- }
-
- byte[] gssInToken = new byte[len];
- gssInToken[0] = selectedQop;
-
- if (logger.isLoggable(Level.FINE)) {
- logger.log(Level.FINE,
- "KRB5CLNT08:Selected protection: {0}; privacy: {1}; integrity: {2}",
- new Object[]{selectedQop,
- Boolean.valueOf(privacy),
- Boolean.valueOf(integrity)});
- }
-
- intToNetworkByteOrder(recvMaxBufSize, gssInToken, 1, 3);
- if (authzID != null) {
- // copy authorization id
- System.arraycopy(authzID, 0, gssInToken, 4, authzID.length);
- logger.log(Level.FINE, "KRB5CLNT09:Authzid: {0}", authzID);
- }
-
- if (logger.isLoggable(Level.FINER)) {
- traceOutput(MY_CLASS_NAME, "doFinalHandshake",
- "KRB5CLNT10:Response [raw]", gssInToken);
- }
-
- gssOutToken = secCtx.wrap(gssInToken,
- 0, gssInToken.length,
- new MessageProp(0 /* qop */, false /* privacy */));
-
- if (logger.isLoggable(Level.FINER)) {
- traceOutput(MY_CLASS_NAME, "doFinalHandshake",
- "KRB5CLNT11:Response [after wrap]", gssOutToken);
- }
-
- completed = true; // server authenticated
-
- return gssOutToken;
- } catch (GSSException e) {
- throw new SaslException("Final handshake failed", e);
- }
- }
-}
--- a/jdk/src/java.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Server.java Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,365 +0,0 @@
-/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.security.sasl.gsskerb;
-
-import javax.security.sasl.*;
-import java.io.*;
-import java.util.Map;
-import java.util.logging.Level;
-
-// JAAS
-import javax.security.auth.callback.*;
-
-// JGSS
-import org.ietf.jgss.*;
-
-/**
- * Implements the GSSAPI SASL server mechanism for Kerberos V5.
- * (<A HREF="http://www.ietf.org/rfc/rfc2222.txt">RFC 2222</A>,
- * <a HREF="http://www.ietf.org/internet-drafts/draft-ietf-cat-sasl-gssapi-00.txt">draft-ietf-cat-sasl-gssapi-00.txt</a>).
- *
- * Expects thread's Subject to contain server's Kerberos credentials
- * - If not, underlying KRB5 mech will attempt to acquire Kerberos creds
- * by logging into Kerberos (via default TextCallbackHandler).
- * - These creds will be used for exchange with client.
- *
- * Required callbacks:
- * - AuthorizeCallback
- * handler must verify that authid/authzids are allowed and set
- * authorized ID to be the canonicalized authzid (if applicable).
- *
- * Environment properties that affect behavior of implementation:
- *
- * javax.security.sasl.qop
- * - quality of protection; list of auth, auth-int, auth-conf; default is "auth"
- * javax.security.sasl.maxbuf
- * - max receive buffer size; default is 65536
- * javax.security.sasl.sendmaxbuffer
- * - max send buffer size; default is 65536; (min with client max recv size)
- *
- * @author Rosanna Lee
- */
-final class GssKrb5Server extends GssKrb5Base implements SaslServer {
- private static final String MY_CLASS_NAME = GssKrb5Server.class.getName();
-
- private int handshakeStage = 0;
- private String peer;
- private String me;
- private String authzid;
- private CallbackHandler cbh;
-
- // When serverName is null, the server will be unbound. We need to save and
- // check the protocol name after the context is established. This value
- // will be null if serverName is not null.
- private final String protocolSaved;
- /**
- * Creates a SASL mechanism with server credentials that it needs
- * to participate in GSS-API/Kerberos v5 authentication exchange
- * with the client.
- */
- GssKrb5Server(String protocol, String serverName,
- Map<String, ?> props, CallbackHandler cbh) throws SaslException {
-
- super(props, MY_CLASS_NAME);
-
- this.cbh = cbh;
-
- String service;
- if (serverName == null) {
- protocolSaved = protocol;
- service = null;
- } else {
- protocolSaved = null;
- service = protocol + "@" + serverName;
- }
-
- logger.log(Level.FINE, "KRB5SRV01:Using service name: {0}", service);
-
- try {
- GSSManager mgr = GSSManager.getInstance();
-
- // Create the name for the requested service entity for Krb5 mech
- GSSName serviceName = service == null ? null:
- mgr.createName(service, GSSName.NT_HOSTBASED_SERVICE, KRB5_OID);
-
- GSSCredential cred = mgr.createCredential(serviceName,
- GSSCredential.INDEFINITE_LIFETIME,
- KRB5_OID, GSSCredential.ACCEPT_ONLY);
-
- // Create a context using the server's credentials
- secCtx = mgr.createContext(cred);
-
- if ((allQop&INTEGRITY_ONLY_PROTECTION) != 0) {
- // Might need integrity
- secCtx.requestInteg(true);
- }
-
- if ((allQop&PRIVACY_PROTECTION) != 0) {
- // Might need privacy
- secCtx.requestConf(true);
- }
- } catch (GSSException e) {
- throw new SaslException("Failure to initialize security context", e);
- }
- logger.log(Level.FINE, "KRB5SRV02:Initialization complete");
- }
-
-
- /**
- * Processes the response data.
- *
- * The client sends response data to which the server must
- * process using GSS_accept_sec_context.
- * As per RFC 2222, the GSS authenication completes (GSS_S_COMPLETE)
- * we do an extra hand shake to determine the negotiated security protection
- * and buffer sizes.
- *
- * @param responseData A non-null but possible empty byte array containing the
- * response data from the client.
- * @return A non-null byte array containing the challenge to be
- * sent to the client, or null when no more data is to be sent.
- */
- public byte[] evaluateResponse(byte[] responseData) throws SaslException {
- if (completed) {
- throw new SaslException(
- "SASL authentication already complete");
- }
-
- if (logger.isLoggable(Level.FINER)) {
- traceOutput(MY_CLASS_NAME, "evaluateResponse",
- "KRB5SRV03:Response [raw]:", responseData);
- }
-
- switch (handshakeStage) {
- case 1:
- return doHandshake1(responseData);
-
- case 2:
- return doHandshake2(responseData);
-
- default:
- // Security context not established yet; continue with accept
-
- try {
- byte[] gssOutToken = secCtx.acceptSecContext(responseData,
- 0, responseData.length);
-
- if (logger.isLoggable(Level.FINER)) {
- traceOutput(MY_CLASS_NAME, "evaluateResponse",
- "KRB5SRV04:Challenge: [after acceptSecCtx]", gssOutToken);
- }
-
- if (secCtx.isEstablished()) {
- handshakeStage = 1;
-
- peer = secCtx.getSrcName().toString();
- me = secCtx.getTargName().toString();
-
- logger.log(Level.FINE,
- "KRB5SRV05:Peer name is : {0}, my name is : {1}",
- new Object[]{peer, me});
-
- // me might take the form of proto@host or proto/host
- if (protocolSaved != null &&
- !protocolSaved.equalsIgnoreCase(me.split("[/@]")[0])) {
- throw new SaslException(
- "GSS context targ name protocol error: " + me);
- }
-
- if (gssOutToken == null) {
- return doHandshake1(EMPTY);
- }
- }
-
- return gssOutToken;
- } catch (GSSException e) {
- throw new SaslException("GSS initiate failed", e);
- }
- }
- }
-
- private byte[] doHandshake1(byte[] responseData) throws SaslException {
- try {
- // Security context already established. responseData
- // should contain no data
- if (responseData != null && responseData.length > 0) {
- throw new SaslException(
- "Handshake expecting no response data from server");
- }
-
- // Construct 4 octets of data:
- // First octet contains bitmask specifying protections supported
- // 2nd-4th octets contains max receive buffer of server
-
- byte[] gssInToken = new byte[4];
- gssInToken[0] = allQop;
- intToNetworkByteOrder(recvMaxBufSize, gssInToken, 1, 3);
-
- if (logger.isLoggable(Level.FINE)) {
- logger.log(Level.FINE,
- "KRB5SRV06:Supported protections: {0}; recv max buf size: {1}",
- new Object[]{allQop,
- recvMaxBufSize});
- }
-
- handshakeStage = 2; // progress to next stage
-
- if (logger.isLoggable(Level.FINER)) {
- traceOutput(MY_CLASS_NAME, "doHandshake1",
- "KRB5SRV07:Challenge [raw]", gssInToken);
- }
-
- byte[] gssOutToken = secCtx.wrap(gssInToken, 0, gssInToken.length,
- new MessageProp(0 /* gop */, false /* privacy */));
-
- if (logger.isLoggable(Level.FINER)) {
- traceOutput(MY_CLASS_NAME, "doHandshake1",
- "KRB5SRV08:Challenge [after wrap]", gssOutToken);
- }
- return gssOutToken;
-
- } catch (GSSException e) {
- throw new SaslException("Problem wrapping handshake1", e);
- }
- }
-
- private byte[] doHandshake2(byte[] responseData) throws SaslException {
- try {
- // Expecting 4 octets from client selected protection
- // and client's receive buffer size
- byte[] gssOutToken = secCtx.unwrap(responseData, 0,
- responseData.length, new MessageProp(0, false));
-
- if (logger.isLoggable(Level.FINER)) {
- traceOutput(MY_CLASS_NAME, "doHandshake2",
- "KRB5SRV09:Response [after unwrap]", gssOutToken);
- }
-
- // First octet is a bit-mask specifying the selected protection
- byte selectedQop = gssOutToken[0];
- if ((selectedQop&allQop) == 0) {
- throw new SaslException("Client selected unsupported protection: "
- + selectedQop);
- }
- if ((selectedQop&PRIVACY_PROTECTION) != 0) {
- privacy = true;
- integrity = true;
- } else if ((selectedQop&INTEGRITY_ONLY_PROTECTION) != 0) {
- integrity = true;
- }
-
- // 2nd-4th octets specifies maximum buffer size expected by
- // client (in network byte order). This is the server's send
- // buffer maximum.
- int clntMaxBufSize = networkByteOrderToInt(gssOutToken, 1, 3);
-
- // Determine the max send buffer size based on what the
- // client is able to receive and our specified max
- sendMaxBufSize = (sendMaxBufSize == 0) ? clntMaxBufSize :
- Math.min(sendMaxBufSize, clntMaxBufSize);
-
- // Update context to limit size of returned buffer
- rawSendSize = secCtx.getWrapSizeLimit(JGSS_QOP, privacy,
- sendMaxBufSize);
-
- if (logger.isLoggable(Level.FINE)) {
- logger.log(Level.FINE,
- "KRB5SRV10:Selected protection: {0}; privacy: {1}; integrity: {2}",
- new Object[]{selectedQop,
- Boolean.valueOf(privacy),
- Boolean.valueOf(integrity)});
- logger.log(Level.FINE,
-"KRB5SRV11:Client max recv size: {0}; server max send size: {1}; rawSendSize: {2}",
- new Object[] {clntMaxBufSize,
- sendMaxBufSize,
- rawSendSize});
- }
-
- // Get authorization identity, if any
- if (gssOutToken.length > 4) {
- try {
- authzid = new String(gssOutToken, 4,
- gssOutToken.length - 4, "UTF-8");
- } catch (UnsupportedEncodingException uee) {
- throw new SaslException ("Cannot decode authzid", uee);
- }
- } else {
- authzid = peer;
- }
- logger.log(Level.FINE, "KRB5SRV12:Authzid: {0}", authzid);
-
- AuthorizeCallback acb = new AuthorizeCallback(peer, authzid);
-
- // In Kerberos, realm is embedded in peer name
- cbh.handle(new Callback[] {acb});
- if (acb.isAuthorized()) {
- authzid = acb.getAuthorizedID();
- completed = true;
- } else {
- // Authorization failed
- throw new SaslException(peer +
- " is not authorized to connect as " + authzid);
- }
-
- return null;
- } catch (GSSException e) {
- throw new SaslException("Final handshake step failed", e);
- } catch (IOException e) {
- throw new SaslException("Problem with callback handler", e);
- } catch (UnsupportedCallbackException e) {
- throw new SaslException("Problem with callback handler", e);
- }
- }
-
- public String getAuthorizationID() {
- if (completed) {
- return authzid;
- } else {
- throw new IllegalStateException("Authentication incomplete");
- }
- }
-
- public Object getNegotiatedProperty(String propName) {
- if (!completed) {
- throw new IllegalStateException("Authentication incomplete");
- }
-
- Object result;
- switch (propName) {
- case Sasl.BOUND_SERVER_NAME:
- try {
- // me might take the form of proto@host or proto/host
- result = me.split("[/@]")[1];
- } catch (Exception e) {
- result = null;
- }
- break;
- default:
- result = super.getNegotiatedProperty(propName);
- }
- return result;
- }
-}
--- a/jdk/src/java.security.jgss/share/classes/org/ietf/jgss/GSSContext.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.security.jgss/share/classes/org/ietf/jgss/GSSContext.java Wed Jul 05 20:01:44 2017 +0200
@@ -25,7 +25,6 @@
package org.ietf.jgss;
-import sun.security.jgss.spi.*;
import java.io.InputStream;
import java.io.OutputStream;
--- a/jdk/src/java.security.jgss/share/classes/org/ietf/jgss/GSSName.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.security.jgss/share/classes/org/ietf/jgss/GSSName.java Wed Jul 05 20:01:44 2017 +0200
@@ -25,10 +25,6 @@
package org.ietf.jgss;
-import sun.security.jgss.spi.*;
-import java.util.Vector;
-import java.util.Enumeration;
-
/**
* This interface encapsulates a single GSS-API principal entity. The
* application obtains an implementation of this interface
--- a/jdk/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java Wed Jul 05 20:01:44 2017 +0200
@@ -25,7 +25,6 @@
package sun.net.www.protocol.http.spnego;
-import com.sun.security.jgss.ExtendedGSSContext;
import java.io.IOException;
import org.ietf.jgss.GSSContext;
@@ -36,6 +35,7 @@
import sun.net.www.protocol.http.HttpCallerInfo;
import sun.net.www.protocol.http.Negotiator;
import sun.security.jgss.GSSManagerImpl;
+import sun.security.jgss.GSSContextImpl;
import sun.security.jgss.GSSUtil;
import sun.security.jgss.HttpCaller;
@@ -102,8 +102,8 @@
GSSContext.DEFAULT_LIFETIME);
// Always respect delegation policy in HTTP/SPNEGO.
- if (context instanceof ExtendedGSSContext) {
- ((ExtendedGSSContext)context).requestDelegPolicy(true);
+ if (context instanceof GSSContextImpl) {
+ ((GSSContextImpl)context).requestDelegPolicy(true);
}
oneToken = context.initSecContext(new byte[0], 0, 0);
}
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSContextImpl.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSContextImpl.java Wed Jul 05 20:01:44 2017 +0200
@@ -33,7 +33,8 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import com.sun.security.jgss.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
/**
* This class represents the JGSS security context and its associated
@@ -87,10 +88,10 @@
* per-message operations are returned in an instance of the MessageProp
* class, which is used as an argument in these calls.</dl>
*/
-class GSSContextImpl implements ExtendedGSSContext {
+public class GSSContextImpl implements GSSContext {
- private final GSSManagerImpl gssManager;
- private final boolean initiator;
+ private GSSManagerImpl gssManager;
+ private boolean initiator;
// private flags for the context state
private static final int PRE_INIT = 1;
@@ -122,6 +123,22 @@
private boolean reqAnonState = false;
private boolean reqDelegPolicyState = false;
+ public GSSContextImpl() {
+ // Useless
+ }
+
+ // Used by new ExtendedGSSContext.ExtendedGSSContextImpl(ctxt)
+ protected GSSContextImpl(GSSContextImpl src) {
+ for (Field f: GSSContextImpl.class.getDeclaredFields()) {
+ if (!Modifier.isStatic(f.getModifiers())) {
+ try {
+ f.set(this, f.get(src));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ }
/**
* Creates a GSSContextImp on the context initiator's side.
*/
@@ -613,7 +630,7 @@
"No mechanism context yet!");
GSSCredentialSpi delCredElement = mechCtxt.getDelegCred();
return (delCredElement == null ?
- null : new GSSCredentialImpl(gssManager, delCredElement));
+ null : GSSManagerImpl.wrap(new GSSCredentialImpl(gssManager, delCredElement)));
}
public boolean isInitiator() throws GSSException {
@@ -633,25 +650,18 @@
// ExtendedGSSContext methods:
- @Override
- public Object inquireSecContext(InquireType type) throws GSSException {
- SecurityManager security = System.getSecurityManager();
- if (security != null) {
- security.checkPermission(new InquireSecContextPermission(type.toString()));
- }
+ public Object inquireSecContext(String type) throws GSSException {
if (mechCtxt == null) {
throw new GSSException(GSSException.NO_CONTEXT);
}
return mechCtxt.inquireSecContext(type);
}
- @Override
public void requestDelegPolicy(boolean state) throws GSSException {
if (mechCtxt == null && initiator)
reqDelegPolicyState = state;
}
- @Override
public boolean getDelegPolicyState() {
if (mechCtxt != null)
return mechCtxt.getDelegPolicyState();
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSCredentialImpl.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSCredentialImpl.java Wed Jul 05 20:01:44 2017 +0200
@@ -27,11 +27,11 @@
import org.ietf.jgss.*;
import sun.security.jgss.spi.*;
+
import java.util.*;
-import com.sun.security.jgss.*;
import sun.security.jgss.spnego.SpNegoCredElement;
-public class GSSCredentialImpl implements ExtendedGSSCredential {
+public class GSSCredentialImpl implements GSSCredential {
private GSSManagerImpl gssManager = null;
private boolean destroyed = false;
@@ -47,6 +47,18 @@
// XXX Optimization for single mech usage
private GSSCredentialSpi tempCred = null;
+ public GSSCredentialImpl() {
+ // Useless
+ }
+
+ // Used by new ExtendedGSSCredential.ExtendedGSSCredentialImpl(cred)
+ protected GSSCredentialImpl(GSSCredentialImpl src) {
+ this.gssManager = src.gssManager;
+ this.destroyed = src.destroyed;
+ this.hashtable = src.hashtable;
+ this.tempCred = src.tempCred;
+ }
+
GSSCredentialImpl(GSSManagerImpl gssManager, int usage)
throws GSSException {
this(gssManager, null, GSSCredential.DEFAULT_LIFETIME,
@@ -140,7 +152,7 @@
((GSSNameImpl)name).getElement(mech));
GSSCredentialSpi cred = tempCred.impersonate(nameElement);
return (cred == null ?
- null : new GSSCredentialImpl(gssManager, cred));
+ null : GSSManagerImpl.wrap(new GSSCredentialImpl(gssManager, cred)));
}
public GSSName getName() throws GSSException {
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSManagerImpl.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSManagerImpl.java Wed Jul 05 20:01:44 2017 +0200
@@ -145,35 +145,35 @@
public GSSCredential createCredential(int usage)
throws GSSException {
- return new GSSCredentialImpl(this, usage);
+ return wrap(new GSSCredentialImpl(this, usage));
}
public GSSCredential createCredential(GSSName aName,
int lifetime, Oid mech, int usage)
throws GSSException {
- return new GSSCredentialImpl(this, aName, lifetime, mech, usage);
+ return wrap(new GSSCredentialImpl(this, aName, lifetime, mech, usage));
}
public GSSCredential createCredential(GSSName aName,
int lifetime, Oid mechs[], int usage)
throws GSSException {
- return new GSSCredentialImpl(this, aName, lifetime, mechs, usage);
+ return wrap(new GSSCredentialImpl(this, aName, lifetime, mechs, usage));
}
public GSSContext createContext(GSSName peer, Oid mech,
GSSCredential myCred, int lifetime)
throws GSSException {
- return new GSSContextImpl(this, peer, mech, myCred, lifetime);
+ return wrap(new GSSContextImpl(this, peer, mech, myCred, lifetime));
}
public GSSContext createContext(GSSCredential myCred)
throws GSSException {
- return new GSSContextImpl(this, myCred);
+ return wrap(new GSSContextImpl(this, myCred));
}
public GSSContext createContext(byte[] interProcessToken)
throws GSSException {
- return new GSSContextImpl(this, interProcessToken);
+ return wrap(new GSSContextImpl(this, interProcessToken));
}
public void addProviderAtFront(Provider p, Oid mech)
@@ -257,4 +257,20 @@
}
return result;
}
+
+ static {
+ // Load the extended JGSS interfaces if exist
+ try {
+ Class.forName("com.sun.security.jgss.Extender");
+ } catch (Exception e) {
+ }
+ }
+
+ static GSSCredential wrap(GSSCredentialImpl cred) {
+ return sun.security.jgss.JgssExtender.getExtender().wrap(cred);
+ }
+
+ static GSSContext wrap(GSSContextImpl ctxt) {
+ return sun.security.jgss.JgssExtender.getExtender().wrap(ctxt);
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/JgssExtender.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.jgss;
+
+import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSCredential;
+
+/**
+ * The extending point of basic JGSS-API.
+ * <p>
+ * If a module wants to extend basic JGSS-API classes, it should extends this
+ * class and register itself as "the extender" using the setExtender method.
+ * When various GSSManager.createXXX methods are called, they will call
+ * "the extender"'s wrap methods to create objects of extended types
+ * instead of basic types.
+ * <p>
+ * We have only one extension now defined in com.sun.security.jgss, and the
+ * registering process is triggered in {@link GSSManagerImpl} by calling
+ * Class.forName("com.sun.security.jgss.Extender"). Only GSSContext
+ * and GSSCredential are extended now.
+ * <p>
+ * The setExtender method should be called before any JGSS call.
+ */
+public class JgssExtender {
+
+ // "The extender"
+ private static volatile JgssExtender theOne = new JgssExtender();
+
+ /**
+ * Gets "the extender". GSSManager calls this method so that it can
+ * wrap basic objects into extended objects.
+ * @return the extender
+ */
+ public static JgssExtender getExtender() {
+ return theOne;
+ }
+
+ /**
+ * Set "the extender" so that GSSManager can create extended objects.
+ */
+ protected static void setExtender(JgssExtender theOne) {
+ JgssExtender.theOne = theOne;
+ }
+
+ /**
+ * Wraps a plain GSSCredential object into an extended type.
+ */
+ public GSSCredential wrap(GSSCredential cred) {
+ return cred;
+ }
+
+ /**
+ * Wraps a plain GSSContext object into an extended type.
+ */
+ public GSSContext wrap(GSSContext ctxt) {
+ return ctxt;
+ }
+}
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/InitSecContextToken.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/InitSecContextToken.java Wed Jul 05 20:01:44 2017 +0200
@@ -25,7 +25,6 @@
package sun.security.jgss.krb5;
-import com.sun.security.jgss.AuthorizationDataEntry;
import org.ietf.jgss.*;
import java.io.InputStream;
import java.io.IOException;
@@ -152,17 +151,7 @@
new KerberosTime(apReq.getCreds().getAuthTime()).toString());
context.setTktFlags(apReq.getCreds().getFlags());
AuthorizationData ad = apReq.getCreds().getAuthzData();
- if (ad == null) {
- context.setAuthzData(null);
- } else {
- AuthorizationDataEntry[] authzData =
- new AuthorizationDataEntry[ad.count()];
- for (int i=0; i<ad.count(); i++) {
- authzData[i] = new AuthorizationDataEntry(
- ad.item(i).adType, ad.item(i).adData);
- }
- context.setAuthzData(authzData);
- }
+ context.setAuthzData(ad);
}
public final KrbApReq getKrbApReq() {
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java Wed Jul 05 20:01:44 2017 +0200
@@ -25,7 +25,6 @@
package sun.security.jgss.krb5;
-import com.sun.security.jgss.InquireType;
import org.ietf.jgss.*;
import sun.misc.HexDumpEncoder;
import sun.security.jgss.GSSUtil;
@@ -48,6 +47,7 @@
import javax.security.auth.kerberos.KerberosPrincipal;
import javax.security.auth.kerberos.KerberosTicket;
import sun.security.krb5.internal.Ticket;
+import sun.security.krb5.internal.AuthorizationData;
/**
* Implements the mechanism specific context class for the Kerberos v5
@@ -1419,30 +1419,30 @@
/**
* Return the mechanism-specific attribute associated with {@code type}.
*/
- public Object inquireSecContext(InquireType type)
+ public Object inquireSecContext(String type)
throws GSSException {
if (!isEstablished()) {
throw new GSSException(GSSException.NO_CONTEXT, -1,
"Security context not established.");
}
switch (type) {
- case KRB5_GET_SESSION_KEY:
+ case "KRB5_GET_SESSION_KEY":
return new KerberosSessionKey(key);
- case KRB5_GET_SESSION_KEY_EX:
+ case "KRB5_GET_SESSION_KEY_EX":
return new javax.security.auth.kerberos.EncryptionKey(
key.getBytes(), key.getEType());
- case KRB5_GET_TKT_FLAGS:
+ case "KRB5_GET_TKT_FLAGS":
return tktFlags.clone();
- case KRB5_GET_AUTHZ_DATA:
+ case "KRB5_GET_AUTHZ_DATA":
if (isInitiator()) {
throw new GSSException(GSSException.UNAVAILABLE, -1,
"AuthzData not available on initiator side.");
} else {
- return (authzData==null)?null:authzData.clone();
+ return authzData;
}
- case KRB5_GET_AUTHTIME:
+ case "KRB5_GET_AUTHTIME":
return authTime;
- case KRB5_GET_KRB_CRED:
+ case "KRB5_GET_KRB_CRED":
if (!isInitiator()) {
throw new GSSException(GSSException.UNAVAILABLE, -1,
"KRB_CRED not available on acceptor side.");
@@ -1470,7 +1470,7 @@
// Helpers for inquireSecContext
private boolean[] tktFlags;
private String authTime;
- private com.sun.security.jgss.AuthorizationDataEntry[] authzData;
+ private AuthorizationData authzData;
public void setTktFlags(boolean[] tktFlags) {
this.tktFlags = tktFlags;
@@ -1480,7 +1480,7 @@
this.authTime = authTime;
}
- public void setAuthzData(com.sun.security.jgss.AuthorizationDataEntry[] authzData) {
+ public void setAuthzData(AuthorizationData authzData) {
this.authzData = authzData;
}
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/spi/GSSContextSpi.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/spi/GSSContextSpi.java Wed Jul 05 20:01:44 2017 +0200
@@ -34,7 +34,6 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Provider;
-import com.sun.security.jgss.*;
/**
* This interface is implemented by a mechanism specific instance of a GSS
@@ -403,6 +402,6 @@
* @throws GSSException see {@link ExtendedGSSContext#inquireSecContext}
* for details
*/
- public Object inquireSecContext(InquireType type)
+ public Object inquireSecContext(String type)
throws GSSException;
}
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoContext.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoContext.java Wed Jul 05 20:01:44 2017 +0200
@@ -25,8 +25,6 @@
package sun.security.jgss.spnego;
-import com.sun.security.jgss.ExtendedGSSContext;
-import com.sun.security.jgss.InquireType;
import java.io.*;
import java.security.Provider;
import org.ietf.jgss.*;
@@ -174,9 +172,9 @@
*/
public final boolean getDelegPolicyState() {
if (isInitiator() && mechContext != null &&
- mechContext instanceof ExtendedGSSContext &&
+ mechContext instanceof GSSContextImpl &&
(state == STATE_IN_PROCESS || state == STATE_DONE)) {
- return ((ExtendedGSSContext)mechContext).getDelegPolicyState();
+ return ((GSSContextImpl)mechContext).getDelegPolicyState();
} else {
return delegPolicyState;
}
@@ -850,7 +848,7 @@
myCred.getInternalCred());
}
mechContext =
- factory.manager.createContext(serverName,
+ factory.manager.createContext(serverName,
internal_mech, cred, GSSContext.DEFAULT_LIFETIME);
mechContext.requestConf(confState);
mechContext.requestInteg(integState);
@@ -858,8 +856,8 @@
mechContext.requestMutualAuth(mutualAuthState);
mechContext.requestReplayDet(replayDetState);
mechContext.requestSequenceDet(sequenceDetState);
- if (mechContext instanceof ExtendedGSSContext) {
- ((ExtendedGSSContext)mechContext).requestDelegPolicy(
+ if (mechContext instanceof GSSContextImpl) {
+ ((GSSContextImpl)mechContext).requestDelegPolicy(
delegPolicyState);
}
}
@@ -890,8 +888,7 @@
cred = new GSSCredentialImpl(factory.manager,
myCred.getInternalCred());
}
- mechContext =
- factory.manager.createContext(cred);
+ mechContext = factory.manager.createContext(cred);
}
// pass token to mechanism acceptSecContext
@@ -1217,14 +1214,14 @@
/**
* Retrieve attribute of the context for {@code type}.
*/
- public Object inquireSecContext(InquireType type)
+ public Object inquireSecContext(String type)
throws GSSException {
if (mechContext == null) {
throw new GSSException(GSSException.NO_CONTEXT, -1,
"Underlying mech not established.");
}
- if (mechContext instanceof ExtendedGSSContext) {
- return ((ExtendedGSSContext)mechContext).inquireSecContext(type);
+ if (mechContext instanceof GSSContextImpl) {
+ return ((GSSContextImpl)mechContext).inquireSecContext(type);
} else {
throw new GSSException(GSSException.BAD_MECH, -1,
"inquireSecContext not supported by underlying mech.");
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoCredElement.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoCredElement.java Wed Jul 05 20:01:44 2017 +0200
@@ -27,8 +27,6 @@
import org.ietf.jgss.*;
import java.security.Provider;
import sun.security.jgss.GSSUtil;
-import sun.security.jgss.ProviderList;
-import sun.security.jgss.GSSCredentialImpl;
import sun.security.jgss.spi.GSSNameSpi;
import sun.security.jgss.spi.GSSCredentialSpi;
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java Wed Jul 05 20:01:44 2017 +0200
@@ -36,7 +36,6 @@
import sun.security.jgss.spnego.NegTokenInit;
import sun.security.jgss.spnego.NegTokenTarg;
import javax.security.auth.kerberos.DelegationPermission;
-import com.sun.security.jgss.InquireType;
import java.io.*;
@@ -623,7 +622,7 @@
dispose();
}
- public Object inquireSecContext(InquireType type)
+ public Object inquireSecContext(String type)
throws GSSException {
throw new GSSException(GSSException.UNAVAILABLE, -1,
"Inquire type not supported.");
--- a/jdk/src/java.sql/share/classes/java/sql/Date.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.sql/share/classes/java/sql/Date.java Wed Jul 05 20:01:44 2017 +0200
@@ -27,6 +27,8 @@
import java.time.Instant;
import java.time.LocalDate;
+import sun.misc.SharedSecrets;
+import sun.misc.JavaLangAccess;
/**
* <P>A thin wrapper around a millisecond value that allows
@@ -42,6 +44,8 @@
*/
public class Date extends java.util.Date {
+ private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
+
/**
* Constructs a <code>Date</code> object initialized with the given
* year, month, and day.
@@ -108,31 +112,27 @@
* JDBC date escape format (yyyy-[m]m-[d]d)
*/
public static Date valueOf(String s) {
+ if (s == null) {
+ throw new java.lang.IllegalArgumentException();
+ }
final int YEAR_LENGTH = 4;
final int MONTH_LENGTH = 2;
final int DAY_LENGTH = 2;
final int MAX_MONTH = 12;
final int MAX_DAY = 31;
- int firstDash;
- int secondDash;
Date d = null;
- if (s == null) {
- throw new java.lang.IllegalArgumentException();
- }
- firstDash = s.indexOf('-');
- secondDash = s.indexOf('-', firstDash + 1);
+ int firstDash = s.indexOf('-');
+ int secondDash = s.indexOf('-', firstDash + 1);
+ int len = s.length();
- if ((firstDash > 0) && (secondDash > 0) && (secondDash < s.length() - 1)) {
- String yyyy = s.substring(0, firstDash);
- String mm = s.substring(firstDash + 1, secondDash);
- String dd = s.substring(secondDash + 1);
- if (yyyy.length() == YEAR_LENGTH &&
- (mm.length() >= 1 && mm.length() <= MONTH_LENGTH) &&
- (dd.length() >= 1 && dd.length() <= DAY_LENGTH)) {
- int year = Integer.parseInt(yyyy);
- int month = Integer.parseInt(mm);
- int day = Integer.parseInt(dd);
+ if ((firstDash > 0) && (secondDash > 0) && (secondDash < len - 1)) {
+ if (firstDash == YEAR_LENGTH &&
+ (secondDash - firstDash > 1 && secondDash - firstDash <= MONTH_LENGTH + 1) &&
+ (len - secondDash > 1 && len - secondDash <= DAY_LENGTH + 1)) {
+ int year = Integer.parseInt(s, 0, firstDash, 10);
+ int month = Integer.parseInt(s, firstDash + 1, secondDash, 10);
+ int day = Integer.parseInt(s, secondDash + 1, len, 10);
if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) {
d = new Date(year - 1900, month - 1, day);
@@ -159,17 +159,34 @@
int month = super.getMonth() + 1;
int day = super.getDate();
- char buf[] = "2000-00-00".toCharArray();
- buf[0] = Character.forDigit(year/1000,10);
- buf[1] = Character.forDigit((year/100)%10,10);
- buf[2] = Character.forDigit((year/10)%10,10);
- buf[3] = Character.forDigit(year%10,10);
- buf[5] = Character.forDigit(month/10,10);
- buf[6] = Character.forDigit(month%10,10);
- buf[8] = Character.forDigit(day/10,10);
- buf[9] = Character.forDigit(day%10,10);
+ char buf[] = new char[10];
+ formatDecimalInt(year, buf, 0, 4);
+ buf[4] = '-';
+ Date.formatDecimalInt(month, buf, 5, 2);
+ buf[7] = '-';
+ Date.formatDecimalInt(day, buf, 8, 2);
+
+ return jla.newStringUnsafe(buf);
+ }
- return new String(buf);
+ /**
+ * Formats an unsigned integer into a char array in decimal output format.
+ * Numbers will be zero-padded or truncated if the string representation
+ * of the integer is smaller than or exceeds len, respectively.
+ *
+ * Should consider moving this to Integer and expose it through
+ * JavaLangAccess similar to Integer::formatUnsignedInt
+ * @param val Value to convert
+ * @param buf Array containing converted value
+ * @param offset Starting pos in buf
+ * @param len length of output value
+ */
+ static void formatDecimalInt(int val, char[] buf, int offset, int len) {
+ int charPos = offset + len;
+ do {
+ buf[--charPos] = (char)('0' + (val % 10));
+ val /= 10;
+ } while (charPos > offset);
}
// Override all the time operations inherited from java.util.Date;
--- a/jdk/src/java.sql/share/classes/java/sql/Time.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.sql/share/classes/java/sql/Time.java Wed Jul 05 20:01:44 2017 +0200
@@ -27,6 +27,8 @@
import java.time.Instant;
import java.time.LocalTime;
+import sun.misc.SharedSecrets;
+import sun.misc.JavaLangAccess;
/**
* <P>A thin wrapper around the <code>java.util.Date</code> class that allows the JDBC
@@ -39,6 +41,8 @@
*/
public class Time extends java.util.Date {
+ private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
+
/**
* Constructs a <code>Time</code> object initialized with the
* given values for the hour, minute, and second.
@@ -90,22 +94,19 @@
* @return a corresponding <code>Time</code> object
*/
public static Time valueOf(String s) {
+ if (s == null) throw new java.lang.IllegalArgumentException();
+
int hour;
int minute;
int second;
- int firstColon;
- int secondColon;
-
- if (s == null) throw new java.lang.IllegalArgumentException();
-
- firstColon = s.indexOf(':');
- secondColon = s.indexOf(':', firstColon+1);
- if ((firstColon > 0) & (secondColon > 0) &
- (secondColon < s.length()-1)) {
- hour = Integer.parseInt(s.substring(0, firstColon));
- minute =
- Integer.parseInt(s.substring(firstColon+1, secondColon));
- second = Integer.parseInt(s.substring(secondColon+1));
+ int firstColon = s.indexOf(':');
+ int secondColon = s.indexOf(':', firstColon + 1);
+ int len = s.length();
+ if (firstColon > 0 && secondColon > 0 &&
+ secondColon < len - 1) {
+ hour = Integer.parseInt(s, 0, firstColon, 10);
+ minute = Integer.parseInt(s, firstColon + 1, secondColon, 10);
+ second = Integer.parseInt(s, secondColon + 1, len, 10);
} else {
throw new java.lang.IllegalArgumentException();
}
@@ -123,26 +124,15 @@
int hour = super.getHours();
int minute = super.getMinutes();
int second = super.getSeconds();
- String hourString;
- String minuteString;
- String secondString;
- if (hour < 10) {
- hourString = "0" + hour;
- } else {
- hourString = Integer.toString(hour);
- }
- if (minute < 10) {
- minuteString = "0" + minute;
- } else {
- minuteString = Integer.toString(minute);
- }
- if (second < 10) {
- secondString = "0" + second;
- } else {
- secondString = Integer.toString(second);
- }
- return (hourString + ":" + minuteString + ":" + secondString);
+ char[] buf = new char[8];
+ Date.formatDecimalInt(hour, buf, 0, 2);
+ buf[2] = ':';
+ Date.formatDecimalInt(minute, buf, 3, 2);
+ buf[5] = ':';
+ Date.formatDecimalInt(second, buf, 6, 2);
+
+ return jla.newStringUnsafe(buf);
}
// Override all the date operations inherited from java.util.Date;
--- a/jdk/src/java.sql/share/classes/java/sql/Timestamp.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/java.sql/share/classes/java/sql/Timestamp.java Wed Jul 05 20:01:44 2017 +0200
@@ -27,7 +27,8 @@
import java.time.Instant;
import java.time.LocalDateTime;
-import java.util.StringTokenizer;
+import sun.misc.SharedSecrets;
+import sun.misc.JavaLangAccess;
/**
* <P>A thin wrapper around <code>java.util.Date</code> that allows
@@ -71,6 +72,8 @@
*/
public class Timestamp extends java.util.Date {
+ private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
+
/**
* Constructs a <code>Timestamp</code> object initialized
* with the given values.
@@ -171,9 +174,6 @@
final int DAY_LENGTH = 2;
final int MAX_MONTH = 12;
final int MAX_DAY = 31;
- String date_s;
- String time_s;
- String nanos_s;
int year = 0;
int month = 0;
int day = 0;
@@ -184,49 +184,38 @@
int firstDash;
int secondDash;
int dividingSpace;
- int firstColon = 0;
- int secondColon = 0;
- int period = 0;
+ int firstColon;
+ int secondColon;
+ int period;
String formatError = "Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]";
- String zeros = "000000000";
- String delimiterDate = "-";
- String delimiterTime = ":";
if (s == null) throw new java.lang.IllegalArgumentException("null string");
// Split the string into date and time components
s = s.trim();
dividingSpace = s.indexOf(' ');
- if (dividingSpace > 0) {
- date_s = s.substring(0,dividingSpace);
- time_s = s.substring(dividingSpace+1);
- } else {
+ if (dividingSpace < 0) {
throw new java.lang.IllegalArgumentException(formatError);
}
// Parse the date
- firstDash = date_s.indexOf('-');
- secondDash = date_s.indexOf('-', firstDash+1);
+ firstDash = s.indexOf('-');
+ secondDash = s.indexOf('-', firstDash+1);
// Parse the time
- if (time_s == null)
- throw new java.lang.IllegalArgumentException(formatError);
- firstColon = time_s.indexOf(':');
- secondColon = time_s.indexOf(':', firstColon+1);
- period = time_s.indexOf('.', secondColon+1);
+ firstColon = s.indexOf(':', dividingSpace + 1);
+ secondColon = s.indexOf(':', firstColon + 1);
+ period = s.indexOf('.', secondColon + 1);
// Convert the date
boolean parsedDate = false;
- if ((firstDash > 0) && (secondDash > 0) && (secondDash < date_s.length() - 1)) {
- String yyyy = date_s.substring(0, firstDash);
- String mm = date_s.substring(firstDash + 1, secondDash);
- String dd = date_s.substring(secondDash + 1);
- if (yyyy.length() == YEAR_LENGTH &&
- (mm.length() >= 1 && mm.length() <= MONTH_LENGTH) &&
- (dd.length() >= 1 && dd.length() <= DAY_LENGTH)) {
- year = Integer.parseInt(yyyy);
- month = Integer.parseInt(mm);
- day = Integer.parseInt(dd);
+ if (firstDash > 0 && secondDash > 0 && secondDash < dividingSpace - 1) {
+ if (firstDash == YEAR_LENGTH &&
+ (secondDash - firstDash > 1 && secondDash - firstDash <= MONTH_LENGTH + 1) &&
+ (dividingSpace - secondDash > 1 && dividingSpace - secondDash <= DAY_LENGTH + 1)) {
+ year = Integer.parseInt(s, 0, firstDash, 10);
+ month = Integer.parseInt(s, firstDash + 1, secondDash, 10);
+ day = Integer.parseInt(s, secondDash + 1, dividingSpace, 10);
if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) {
parsedDate = true;
@@ -238,25 +227,27 @@
}
// Convert the time; default missing nanos
- if ((firstColon > 0) & (secondColon > 0) &
- (secondColon < time_s.length()-1)) {
- hour = Integer.parseInt(time_s.substring(0, firstColon));
- minute =
- Integer.parseInt(time_s.substring(firstColon+1, secondColon));
- if ((period > 0) & (period < time_s.length()-1)) {
- second =
- Integer.parseInt(time_s.substring(secondColon+1, period));
- nanos_s = time_s.substring(period+1);
- if (nanos_s.length() > 9)
+ int len = s.length();
+ if (firstColon > 0 && secondColon > 0 && secondColon < len - 1) {
+ hour = Integer.parseInt(s, dividingSpace + 1, firstColon, 10);
+ minute = Integer.parseInt(s, firstColon + 1, secondColon, 10);
+ if (period > 0 && period < len - 1) {
+ second = Integer.parseInt(s, secondColon + 1, period, 10);
+ int nanoPrecision = len - (period + 1);
+ if (nanoPrecision > 9)
throw new java.lang.IllegalArgumentException(formatError);
- if (!Character.isDigit(nanos_s.charAt(0)))
+ if (!Character.isDigit(s.charAt(period + 1)))
throw new java.lang.IllegalArgumentException(formatError);
- nanos_s = nanos_s + zeros.substring(0,9-nanos_s.length());
- a_nanos = Integer.parseInt(nanos_s);
+ int tmpNanos = Integer.parseInt(s, period + 1, len, 10);
+ while (nanoPrecision < 9) {
+ tmpNanos *= 10;
+ nanoPrecision++;
+ }
+ a_nanos = tmpNanos;
} else if (period > 0) {
throw new java.lang.IllegalArgumentException(formatError);
} else {
- second = Integer.parseInt(time_s.substring(secondColon+1));
+ second = Integer.parseInt(s, secondColon + 1, len, 10);
}
} else {
throw new java.lang.IllegalArgumentException(formatError);
@@ -274,95 +265,53 @@
* <code>yyyy-mm-dd hh:mm:ss.fffffffff</code> format
*/
@SuppressWarnings("deprecation")
- public String toString () {
-
+ public String toString() {
int year = super.getYear() + 1900;
int month = super.getMonth() + 1;
int day = super.getDate();
int hour = super.getHours();
int minute = super.getMinutes();
int second = super.getSeconds();
- String yearString;
- String monthString;
- String dayString;
- String hourString;
- String minuteString;
- String secondString;
- String nanosString;
- String zeros = "000000000";
- String yearZeros = "0000";
- StringBuffer timestampBuf;
- if (year < 1000) {
- // Add leading zeros
- yearString = "" + year;
- yearString = yearZeros.substring(0, (4-yearString.length())) +
- yearString;
- } else {
- yearString = "" + year;
- }
- if (month < 10) {
- monthString = "0" + month;
- } else {
- monthString = Integer.toString(month);
- }
- if (day < 10) {
- dayString = "0" + day;
+ int trailingZeros = 0;
+ int tmpNanos = nanos;
+ if (tmpNanos == 0) {
+ trailingZeros = 8;
} else {
- dayString = Integer.toString(day);
- }
- if (hour < 10) {
- hourString = "0" + hour;
- } else {
- hourString = Integer.toString(hour);
- }
- if (minute < 10) {
- minuteString = "0" + minute;
- } else {
- minuteString = Integer.toString(minute);
- }
- if (second < 10) {
- secondString = "0" + second;
- } else {
- secondString = Integer.toString(second);
- }
- if (nanos == 0) {
- nanosString = "0";
- } else {
- nanosString = Integer.toString(nanos);
-
- // Add leading zeros
- nanosString = zeros.substring(0, (9-nanosString.length())) +
- nanosString;
-
- // Truncate trailing zeros
- char[] nanosChar = new char[nanosString.length()];
- nanosString.getChars(0, nanosString.length(), nanosChar, 0);
- int truncIndex = 8;
- while (nanosChar[truncIndex] == '0') {
- truncIndex--;
+ while (tmpNanos % 10 == 0) {
+ tmpNanos /= 10;
+ trailingZeros++;
}
-
- nanosString = new String(nanosChar, 0, truncIndex + 1);
}
- // do a string buffer here instead.
- timestampBuf = new StringBuffer(20+nanosString.length());
- timestampBuf.append(yearString);
- timestampBuf.append("-");
- timestampBuf.append(monthString);
- timestampBuf.append("-");
- timestampBuf.append(dayString);
- timestampBuf.append(" ");
- timestampBuf.append(hourString);
- timestampBuf.append(":");
- timestampBuf.append(minuteString);
- timestampBuf.append(":");
- timestampBuf.append(secondString);
- timestampBuf.append(".");
- timestampBuf.append(nanosString);
+ // 8058429: To comply with current JCK tests, we need to deal with year
+ // being any number between 0 and 292278995
+ int count = 10000;
+ int yearSize = 4;
+ do {
+ if (year < count) {
+ break;
+ }
+ yearSize++;
+ count *= 10;
+ } while (count < 1000000000);
- return (timestampBuf.toString());
+ char[] buf = new char[25 + yearSize - trailingZeros];
+ Date.formatDecimalInt(year, buf, 0, yearSize);
+ buf[yearSize] = '-';
+ Date.formatDecimalInt(month, buf, yearSize + 1, 2);
+ buf[yearSize + 3] = '-';
+ Date.formatDecimalInt(day, buf, yearSize + 4, 2);
+ buf[yearSize + 6] = ' ';
+ Date.formatDecimalInt(hour, buf, yearSize + 7, 2);
+ buf[yearSize + 9] = ':';
+ Date.formatDecimalInt(minute, buf, yearSize + 10, 2);
+ buf[yearSize + 12] = ':';
+ Date.formatDecimalInt(second, buf, yearSize + 13, 2);
+ buf[yearSize + 15] = '.';
+ Date.formatDecimalInt(tmpNanos, buf, yearSize + 16, 9 - trailingZeros);
+
+ return jla.newStringUnsafe(buf);
}
/**
--- a/jdk/src/jdk.localedata/META-INF/cldrdata-services/sun.util.locale.provider.LocaleDataMetaInfo Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/src/jdk.localedata/META-INF/cldrdata-services/sun.util.locale.provider.LocaleDataMetaInfo Wed Jul 05 20:01:44 2017 +0200
@@ -1,1 +1,1 @@
-sun.util.cldr.CLDRLocaleDataMetaInfo
+sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.security.jgss/share/classes/com/sun/security/jgss/AuthorizationDataEntry.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.security.jgss;
+
+/**
+ * Kerberos 5 AuthorizationData entry.
+ */
+@jdk.Exported
+public final class AuthorizationDataEntry {
+
+ private final int type;
+ private final byte[] data;
+
+ /**
+ * Create an AuthorizationDataEntry object.
+ * @param type the ad-type
+ * @param data the ad-data, a copy of the data will be saved
+ * inside the object.
+ */
+ public AuthorizationDataEntry(int type, byte[] data) {
+ this.type = type;
+ this.data = data.clone();
+ }
+
+ /**
+ * Get the ad-type field.
+ * @return ad-type
+ */
+ public int getType() {
+ return type;
+ }
+
+ /**
+ * Get a copy of the ad-data field.
+ * @return ad-data
+ */
+ public byte[] getData() {
+ return data.clone();
+ }
+
+ public String toString() {
+ return "AuthorizationDataEntry: type="+type+", data=" +
+ data.length + " bytes:\n" +
+ new sun.misc.HexDumpEncoder().encodeBuffer(data);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.security.jgss/share/classes/com/sun/security/jgss/ExtendedGSSContext.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.security.jgss;
+
+import org.ietf.jgss.*;
+import sun.security.jgss.GSSContextImpl;
+import sun.security.krb5.internal.AuthorizationData;
+
+/**
+ * The extended GSSContext interface for supporting additional
+ * functionalities not defined by {@code org.ietf.jgss.GSSContext},
+ * such as querying context-specific attributes.
+ */
+@jdk.Exported
+public interface ExtendedGSSContext extends GSSContext {
+
+ // The impl is almost identical to GSSContextImpl with only 2 differences:
+ // 1. It implements the extended interface
+ // 2. It translates result to data types here in inquireSecContext
+ static class ExtendedGSSContextImpl extends GSSContextImpl
+ implements ExtendedGSSContext {
+
+ public ExtendedGSSContextImpl(GSSContextImpl old) {
+ super(old);
+ }
+
+ @Override
+ public Object inquireSecContext(InquireType type) throws GSSException {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkPermission(
+ new InquireSecContextPermission(type.toString()));
+ }
+ Object output = super.inquireSecContext(type.name());
+ if (output != null) {
+ if (type == InquireType.KRB5_GET_AUTHZ_DATA) {
+ AuthorizationData ad = (AuthorizationData) output;
+ AuthorizationDataEntry[] authzData =
+ new AuthorizationDataEntry[ad.count()];
+ for (int i = 0; i < ad.count(); i++) {
+ authzData[i] = new AuthorizationDataEntry(
+ ad.item(i).adType, ad.item(i).adData);
+ }
+ output = authzData;
+ }
+ }
+ return output;
+ }
+ }
+
+ /**
+ * Return the mechanism-specific attribute associated with {@code type}.
+ * <p>
+ * If there is a security manager, an {@link InquireSecContextPermission}
+ * with the name {@code type.mech} must be granted. Otherwise, this could
+ * result in a {@link SecurityException}.
+ * <p>
+ * Example:
+ * <pre>
+ * GSSContext ctxt = m.createContext(...)
+ * // Establishing the context
+ * if (ctxt instanceof ExtendedGSSContext) {
+ * ExtendedGSSContext ex = (ExtendedGSSContext)ctxt;
+ * try {
+ * Key key = (key)ex.inquireSecContext(
+ * InquireType.KRB5_GET_SESSION_KEY);
+ * // read key info
+ * } catch (GSSException gsse) {
+ * // deal with exception
+ * }
+ * }
+ * </pre>
+ * @param type the type of the attribute requested
+ * @return the attribute, see the method documentation for details.
+ * @throws GSSException containing the following
+ * major error codes:
+ * {@link GSSException#BAD_MECH GSSException.BAD_MECH} if the mechanism
+ * does not support this method,
+ * {@link GSSException#UNAVAILABLE GSSException.UNAVAILABLE} if the
+ * type specified is not supported,
+ * {@link GSSException#NO_CONTEXT GSSException.NO_CONTEXT} if the
+ * security context is invalid,
+ * {@link GSSException#FAILURE GSSException.FAILURE} for other
+ * unspecified failures.
+ * @throws SecurityException if a security manager exists and a proper
+ * {@link InquireSecContextPermission} is not granted.
+ * @see InquireSecContextPermission
+ * @see InquireType
+ */
+ public Object inquireSecContext(InquireType type)
+ throws GSSException;
+
+ /**
+ * Requests that the delegation policy be respected. When a true value is
+ * requested, the underlying context would use the delegation policy
+ * defined by the environment as a hint to determine whether credentials
+ * delegation should be performed. This request can only be made on the
+ * context initiator's side and it has to be done prior to the first
+ * call to <code>initSecContext</code>.
+ * <p>
+ * When this flag is false, delegation will only be tried when the
+ * {@link GSSContext#requestCredDeleg(boolean) credentials delegation flag}
+ * is true.
+ * <p>
+ * When this flag is true but the
+ * {@link GSSContext#requestCredDeleg(boolean) credentials delegation flag}
+ * is false, delegation will be only tried if the delegation policy permits
+ * delegation.
+ * <p>
+ * When both this flag and the
+ * {@link GSSContext#requestCredDeleg(boolean) credentials delegation flag}
+ * are true, delegation will be always tried. However, if the delegation
+ * policy does not permit delegation, the value of
+ * {@link #getDelegPolicyState} will be false, even
+ * if delegation is performed successfully.
+ * <p>
+ * In any case, if the delegation is not successful, the value returned
+ * by {@link GSSContext#getCredDelegState()} is false, and the value
+ * returned by {@link #getDelegPolicyState()} is also false.
+ * <p>
+ * Not all mechanisms support delegation policy. Therefore, the
+ * application should check to see if the request was honored with the
+ * {@link #getDelegPolicyState() getDelegPolicyState} method. When
+ * delegation policy is not supported, <code>requestDelegPolicy</code>
+ * should return silently without throwing an exception.
+ * <p>
+ * Note: for the Kerberos 5 mechanism, the delegation policy is expressed
+ * through the OK-AS-DELEGATE flag in the service ticket. When it's true,
+ * the KDC permits delegation to the target server. In a cross-realm
+ * environment, in order for delegation be permitted, all cross-realm TGTs
+ * on the authentication path must also have the OK-AS-DELAGATE flags set.
+ * @param state true if the policy should be respected
+ * @throws GSSException containing the following
+ * major error codes:
+ * {@link GSSException#FAILURE GSSException.FAILURE}
+ */
+ public void requestDelegPolicy(boolean state) throws GSSException;
+
+ /**
+ * Returns the delegation policy response. Called after a security context
+ * is established. This method can be only called on the initiator's side.
+ * See {@link ExtendedGSSContext#requestDelegPolicy}.
+ * @return the delegation policy response
+ */
+ public boolean getDelegPolicyState();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.security.jgss/share/classes/com/sun/security/jgss/ExtendedGSSCredential.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.security.jgss;
+
+import org.ietf.jgss.*;
+import sun.security.jgss.GSSCredentialImpl;
+
+/**
+ * The extended GSSCredential interface for supporting additional
+ * functionalities not defined by {@code org.ietf.jgss.GSSCredential}.
+ * @since 1.8
+ */
+@jdk.Exported
+public interface ExtendedGSSCredential extends GSSCredential {
+
+ static class ExtendedGSSCredentialImpl extends GSSCredentialImpl
+ implements ExtendedGSSCredential {
+
+ public ExtendedGSSCredentialImpl(GSSCredentialImpl old) {
+ super(old);
+ }
+ }
+
+ /**
+ * Impersonates a principal. In Kerberos, this can be implemented
+ * using the Microsoft S4U2self extension.
+ * <p>
+ * A {@link GSSException#NO_CRED GSSException.NO_CRED} will be thrown if the
+ * impersonation fails. A {@link GSSException#FAILURE GSSException.FAILURE}
+ * will be thrown if the impersonation method is not available to this
+ * credential object.
+ * @param name the name of the principal to impersonate
+ * @return a credential for that principal
+ * @throws GSSException containing the following
+ * major error codes:
+ * {@link GSSException#NO_CRED GSSException.NO_CRED}
+ * {@link GSSException#FAILURE GSSException.FAILURE}
+ */
+ public GSSCredential impersonate(GSSName name) throws GSSException;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.security.jgss/share/classes/com/sun/security/jgss/Extender.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.security.jgss;
+
+import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSCredential;
+import sun.security.jgss.GSSContextImpl;
+import sun.security.jgss.GSSCredentialImpl;
+import sun.security.jgss.JgssExtender;
+
+// The com.sun.security.jgss extension to JGSS-API
+class Extender extends JgssExtender {
+
+ static {
+ JgssExtender.setExtender(new Extender());
+ }
+
+ public GSSCredential wrap(GSSCredential cred) {
+ if (cred instanceof ExtendedGSSCredential.ExtendedGSSCredentialImpl) {
+ return cred;
+ } else {
+ return new ExtendedGSSCredential.ExtendedGSSCredentialImpl((GSSCredentialImpl)cred);
+ }
+ }
+
+ public GSSContext wrap(GSSContext ctxt) {
+ if (ctxt instanceof ExtendedGSSContext.ExtendedGSSContextImpl) {
+ return ctxt;
+ } else {
+ return new ExtendedGSSContext.ExtendedGSSContextImpl((GSSContextImpl)ctxt);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.security.jgss/share/classes/com/sun/security/jgss/GSSUtil.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.security.jgss;
+
+import javax.security.auth.Subject;
+import org.ietf.jgss.GSSName;
+import org.ietf.jgss.GSSCredential;
+
+/**
+ * GSS-API Utilities for using in conjunction with Sun Microsystem's
+ * implementation of Java GSS-API.
+ */
+@jdk.Exported
+public class GSSUtil {
+
+ /**
+ * Use this method to convert a GSSName and GSSCredential into a
+ * Subject. Typically this would be done by a server that wants to
+ * impersonate a client thread at the Java level by setting a client
+ * Subject in the current access control context. If the server is merely
+ * interested in using a principal based policy in its local JVM, then
+ * it only needs to provide the GSSName of the client.
+ *
+ * The elements from the GSSName are placed in the principals set of this
+ * Subject and those from the GSSCredential are placed in the private
+ * credentials set of the Subject. Any Kerberos specific elements that
+ * are added to the subject will be instances of the standard Kerberos
+ * implementation classes defined in javax.security.auth.kerberos.
+ *
+ * @return a Subject with the entries that contain elements from the
+ * given GSSName and GSSCredential.
+ *
+ * @param principals a GSSName containing one or more mechanism specific
+ * representations of the same entity. These mechanism specific
+ * representations will be populated in the returned Subject's principal
+ * set.
+ *
+ * @param credentials a GSSCredential containing one or more mechanism
+ * specific credentials for the same entity. These mechanism specific
+ * credentials will be populated in the returned Subject's private
+ * credential set. Passing in a value of null will imply that the private
+ * credential set should be left empty.
+ */
+ public static Subject createSubject(GSSName principals,
+ GSSCredential credentials) {
+
+ return sun.security.jgss.GSSUtil.getSubject(principals,
+ credentials);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.security.jgss/share/classes/com/sun/security/jgss/InquireSecContextPermission.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.security.jgss;
+
+import java.security.BasicPermission;
+
+/**
+ * This class is used to protect various attributes of an established
+ * GSS security context that can be accessed using the
+ * {@link com.sun.security.jgss.ExtendedGSSContext#inquireSecContext}
+ * method.
+ *
+ * <p>The target name is the {@link InquireType} allowed.
+ */
+@jdk.Exported
+public final class InquireSecContextPermission extends BasicPermission {
+ private static final long serialVersionUID = -7131173349668647297L;
+
+ /**
+ * Constructs a new {@code InquireSecContextPermission} object with
+ * the specified name. The name is the symbolic name of the
+ * {@link InquireType} allowed.
+ *
+ * @param name the {@link InquireType} allowed by this
+ * permission. "*" means all {@link InquireType}s are allowed.
+ *
+ * @throws NullPointerException if <code>name</code> is <code>null</code>.
+ * @throws IllegalArgumentException if <code>name</code> is empty.
+ */
+ public InquireSecContextPermission(String name) {
+ super(name);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.security.jgss/share/classes/com/sun/security/jgss/InquireType.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.security.jgss;
+
+/**
+ * Attribute types that can be specified as an argument of
+ * {@link com.sun.security.jgss.ExtendedGSSContext#inquireSecContext}
+ */
+@jdk.Exported
+public enum InquireType {
+ /**
+ * Attribute type for retrieving the session key of an established
+ * Kerberos 5 security context. The returned object is an instance of
+ * {@link java.security.Key}, which has the following properties:
+ * <ul>
+ * <li>Algorithm: enctype as a string, where
+ * enctype is defined in RFC 3961, section 8.
+ * <li>Format: "RAW"
+ * <li>Encoded form: the raw key bytes, not in any ASN.1 encoding
+ * </ul>
+ * @deprecated as of 1.9, replaced by {@link #KRB5_GET_SESSION_KEY_EX}
+ * which returns an instance of
+ * {@link javax.security.auth.kerberos.EncryptionKey}
+ * that implements the {@link javax.crypto.SecretKey} interface and
+ * has similar methods with {@link javax.security.auth.kerberos.KerberosKey}.
+ */
+ @Deprecated
+ KRB5_GET_SESSION_KEY,
+ /**
+ * Attribute type for retrieving the session key of an
+ * established Kerberos 5 security context. The return value is an
+ * instance of {@link javax.security.auth.kerberos.EncryptionKey}.
+ *
+ * @since 1.9
+ */
+ KRB5_GET_SESSION_KEY_EX,
+ /**
+ * Attribute type for retrieving the service ticket flags of an
+ * established Kerberos 5 security context. The returned object is
+ * a boolean array for the service ticket flags, which is long enough
+ * to contain all true bits. This means if the user wants to get the
+ * <em>n</em>'th bit but the length of the returned array is less than
+ * <em>n</em>, it is regarded as false.
+ */
+ KRB5_GET_TKT_FLAGS,
+ /**
+ * Attribute type for retrieving the authorization data in the
+ * service ticket of an established Kerberos 5 security context.
+ * Only supported on the acceptor side.
+ */
+ KRB5_GET_AUTHZ_DATA,
+ /**
+ * Attribute type for retrieving the authtime in the service ticket
+ * of an established Kerberos 5 security context. The returned object
+ * is a String object in the standard KerberosTime format defined in
+ * RFC 4120 Section 5.2.3.
+ */
+ KRB5_GET_AUTHTIME,
+ /**
+ * Attribute type for retrieving the KRB_CRED message that an initiator
+ * is about to send to an acceptor. The return type is an instance of
+ * {@link javax.security.auth.kerberos.KerberosCredMessage}.
+ *
+ * @since 1.9
+ */
+ KRB5_GET_KRB_CRED,
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.security.jgss/share/classes/com/sun/security/jgss/package-info.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+@jdk.Exported
+package com.sun.security.jgss;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/FactoryImpl.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.security.sasl.gsskerb;
+
+import javax.security.sasl.*;
+import com.sun.security.sasl.util.PolicyUtils;
+
+import java.util.Map;
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ * Client/server factory for GSSAPI (Kerberos V5) SASL client/server mechs.
+ * See GssKrb5Client/GssKrb5Server for input requirements.
+ *
+ * @author Rosanna Lee
+ */
+public final class FactoryImpl implements SaslClientFactory, SaslServerFactory {
+ private static final String myMechs[] = {
+ "GSSAPI"};
+
+ private static final int mechPolicies[] = {
+ PolicyUtils.NOPLAINTEXT|PolicyUtils.NOANONYMOUS|PolicyUtils.NOACTIVE
+ };
+
+ private static final int GSS_KERB_V5 = 0;
+
+ public FactoryImpl() {
+ }
+
+ public SaslClient createSaslClient(String[] mechs,
+ String authorizationId,
+ String protocol,
+ String serverName,
+ Map<String,?> props,
+ CallbackHandler cbh) throws SaslException {
+
+ for (int i = 0; i < mechs.length; i++) {
+ if (mechs[i].equals(myMechs[GSS_KERB_V5])
+ && PolicyUtils.checkPolicy(mechPolicies[GSS_KERB_V5], props)) {
+ return new GssKrb5Client(
+ authorizationId,
+ protocol,
+ serverName,
+ props,
+ cbh);
+ }
+ }
+ return null;
+ };
+
+ public SaslServer createSaslServer(String mech,
+ String protocol,
+ String serverName,
+ Map<String,?> props,
+ CallbackHandler cbh) throws SaslException {
+ if (mech.equals(myMechs[GSS_KERB_V5])
+ && PolicyUtils.checkPolicy(mechPolicies[GSS_KERB_V5], props)) {
+ if (cbh == null) {
+ throw new SaslException(
+ "Callback handler with support for AuthorizeCallback required");
+ }
+ return new GssKrb5Server(
+ protocol,
+ serverName,
+ props,
+ cbh);
+ }
+ return null;
+ };
+
+ public String[] getMechanismNames(Map<String,?> props) {
+ return PolicyUtils.filterMechs(myMechs, mechPolicies, props);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Base.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package com.sun.security.sasl.gsskerb;
+
+import java.util.Locale;
+import java.util.Map;
+import java.util.logging.Level;
+import javax.security.sasl.*;
+import com.sun.security.sasl.util.AbstractSaslImpl;
+import org.ietf.jgss.*;
+import com.sun.security.jgss.ExtendedGSSContext;
+import com.sun.security.jgss.InquireType;
+
+abstract class GssKrb5Base extends AbstractSaslImpl {
+
+ private static final String KRB5_OID_STR = "1.2.840.113554.1.2.2";
+ protected static Oid KRB5_OID;
+ protected static final byte[] EMPTY = new byte[0];
+
+ static {
+ try {
+ KRB5_OID = new Oid(KRB5_OID_STR);
+ } catch (GSSException ignore) {}
+ }
+
+ protected GSSContext secCtx = null;
+ protected static final int JGSS_QOP = 0; // unrelated to SASL QOP mask
+
+ protected GssKrb5Base(Map<String, ?> props, String className)
+ throws SaslException {
+ super(props, className);
+ }
+
+ /**
+ * Retrieves this mechanism's name.
+ *
+ * @return The string "GSSAPI".
+ */
+ public String getMechanismName() {
+ return "GSSAPI";
+ }
+
+ @Override
+ public Object getNegotiatedProperty(String propName) {
+ if (!completed) {
+ throw new IllegalStateException("Authentication incomplete");
+ }
+ String xprefix = "com.sun.security.jgss.inquiretype.";
+ if (propName.startsWith(xprefix)) {
+ String type = propName.substring(xprefix.length());
+ if (logger.isLoggable(Level.FINEST)) {
+ logger.logp(Level.FINE, "GssKrb5Base",
+ "getNegotiatedProperty", propName);
+ }
+ for (InquireType t: InquireType.values()) {
+ if (t.name().toLowerCase(Locale.US).equals(type)) {
+ try {
+ return ((ExtendedGSSContext)secCtx).inquireSecContext(t);
+ } catch (GSSException e) {
+ if (logger.isLoggable(Level.FINEST)) {
+ logger.log(Level.WARNING, "inquireSecContext error", e);
+ }
+ return null;
+ }
+ }
+ }
+ // No such InquireType. Although not likely to be defined
+ // as a property in a parent class, still try it.
+ }
+ return super.getNegotiatedProperty(propName);
+ }
+
+ public byte[] unwrap(byte[] incoming, int start, int len)
+ throws SaslException {
+ if (!completed) {
+ throw new IllegalStateException("GSSAPI authentication not completed");
+ }
+
+ // integrity will be true if either privacy or integrity negotiated
+ if (!integrity) {
+ throw new IllegalStateException("No security layer negotiated");
+ }
+
+ try {
+ MessageProp msgProp = new MessageProp(JGSS_QOP, privacy);
+ byte[] answer = secCtx.unwrap(incoming, start, len, msgProp);
+ if (logger.isLoggable(Level.FINEST)) {
+ traceOutput(myClassName, "KRB501:Unwrap", "incoming: ",
+ incoming, start, len);
+ traceOutput(myClassName, "KRB502:Unwrap", "unwrapped: ",
+ answer, 0, answer.length);
+ }
+ return answer;
+ } catch (GSSException e) {
+ throw new SaslException("Problems unwrapping SASL buffer", e);
+ }
+ }
+
+ public byte[] wrap(byte[] outgoing, int start, int len) throws SaslException {
+ if (!completed) {
+ throw new IllegalStateException("GSSAPI authentication not completed");
+ }
+
+ // integrity will be true if either privacy or integrity negotiated
+ if (!integrity) {
+ throw new IllegalStateException("No security layer negotiated");
+ }
+
+ // Generate GSS token
+ try {
+ MessageProp msgProp = new MessageProp(JGSS_QOP, privacy);
+ byte[] answer = secCtx.wrap(outgoing, start, len, msgProp);
+ if (logger.isLoggable(Level.FINEST)) {
+ traceOutput(myClassName, "KRB503:Wrap", "outgoing: ",
+ outgoing, start, len);
+ traceOutput(myClassName, "KRB504:Wrap", "wrapped: ",
+ answer, 0, answer.length);
+ }
+ return answer;
+
+ } catch (GSSException e) {
+ throw new SaslException("Problem performing GSS wrap", e);
+ }
+ }
+
+ public void dispose() throws SaslException {
+ if (secCtx != null) {
+ try {
+ secCtx.dispose();
+ } catch (GSSException e) {
+ throw new SaslException("Problem disposing GSS context", e);
+ }
+ secCtx = null;
+ }
+ }
+
+ protected void finalize() throws Throwable {
+ dispose();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Client.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.security.sasl.gsskerb;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.logging.Level;
+import javax.security.sasl.*;
+
+// JAAS
+import javax.security.auth.callback.CallbackHandler;
+
+// JGSS
+import org.ietf.jgss.*;
+
+/**
+ * Implements the GSSAPI SASL client mechanism for Kerberos V5.
+ * (<A HREF="http://www.ietf.org/rfc/rfc2222.txt">RFC 2222</A>,
+ * <a HREF="http://www.ietf.org/internet-drafts/draft-ietf-cat-sasl-gssapi-04.txt">draft-ietf-cat-sasl-gssapi-04.txt</a>).
+ * It uses the Java Bindings for GSSAPI
+ * (<A HREF="http://www.ietf.org/rfc/rfc2853.txt">RFC 2853</A>)
+ * for getting GSSAPI/Kerberos V5 support.
+ *
+ * The client/server interactions are:
+ * C0: bind (GSSAPI, initial response)
+ * S0: sasl-bind-in-progress, challenge 1 (output of accept_sec_context or [])
+ * C1: bind (GSSAPI, response 1 (output of init_sec_context or []))
+ * S1: sasl-bind-in-progress challenge 2 (security layer, server max recv size)
+ * C2: bind (GSSAPI, response 2 (security layer, client max recv size, authzid))
+ * S2: bind success response
+ *
+ * Expects the client's credentials to be supplied from the
+ * javax.security.sasl.credentials property or from the thread's Subject.
+ * Otherwise the underlying KRB5 mech will attempt to acquire Kerberos creds
+ * by logging into Kerberos (via default TextCallbackHandler).
+ * These creds will be used for exchange with server.
+ *
+ * Required callbacks: none.
+ *
+ * Environment properties that affect behavior of implementation:
+ *
+ * javax.security.sasl.qop
+ * - quality of protection; list of auth, auth-int, auth-conf; default is "auth"
+ * javax.security.sasl.maxbuf
+ * - max receive buffer size; default is 65536
+ * javax.security.sasl.sendmaxbuffer
+ * - max send buffer size; default is 65536; (min with server max recv size)
+ *
+ * javax.security.sasl.server.authentication
+ * - "true" means require mutual authentication; default is "false"
+ *
+ * javax.security.sasl.credentials
+ * - an {@link org.ietf.jgss.GSSCredential} used for delegated authentication.
+ *
+ * @author Rosanna Lee
+ */
+
+final class GssKrb5Client extends GssKrb5Base implements SaslClient {
+ // ---------------- Constants -----------------
+ private static final String MY_CLASS_NAME = GssKrb5Client.class.getName();
+
+ private boolean finalHandshake = false;
+ private boolean mutual = false; // default false
+ private byte[] authzID;
+
+ /**
+ * Creates a SASL mechanism with client credentials that it needs
+ * to participate in GSS-API/Kerberos v5 authentication exchange
+ * with the server.
+ */
+ GssKrb5Client(String authzID, String protocol, String serverName,
+ Map<String, ?> props, CallbackHandler cbh) throws SaslException {
+
+ super(props, MY_CLASS_NAME);
+
+ String service = protocol + "@" + serverName;
+ logger.log(Level.FINE, "KRB5CLNT01:Requesting service name: {0}",
+ service);
+
+ try {
+ GSSManager mgr = GSSManager.getInstance();
+
+ // Create the name for the requested service entity for Krb5 mech
+ GSSName acceptorName = mgr.createName(service,
+ GSSName.NT_HOSTBASED_SERVICE, KRB5_OID);
+
+ // Parse properties to check for supplied credentials
+ GSSCredential credentials = null;
+ if (props != null) {
+ Object prop = props.get(Sasl.CREDENTIALS);
+ if (prop != null && prop instanceof GSSCredential) {
+ credentials = (GSSCredential) prop;
+ logger.log(Level.FINE,
+ "KRB5CLNT01:Using the credentials supplied in " +
+ "javax.security.sasl.credentials");
+ }
+ }
+
+ // Create a context using credentials for Krb5 mech
+ secCtx = mgr.createContext(acceptorName,
+ KRB5_OID, /* mechanism */
+ credentials, /* credentials */
+ GSSContext.INDEFINITE_LIFETIME);
+
+ // Request credential delegation when credentials have been supplied
+ if (credentials != null) {
+ secCtx.requestCredDeleg(true);
+ }
+
+ // Parse properties to set desired context options
+ if (props != null) {
+ // Mutual authentication
+ String prop = (String)props.get(Sasl.SERVER_AUTH);
+ if (prop != null) {
+ mutual = "true".equalsIgnoreCase(prop);
+ }
+ }
+ secCtx.requestMutualAuth(mutual);
+
+ // Always specify potential need for integrity and confidentiality
+ // Decision will be made during final handshake
+ secCtx.requestConf(true);
+ secCtx.requestInteg(true);
+
+ } catch (GSSException e) {
+ throw new SaslException("Failure to initialize security context", e);
+ }
+
+ if (authzID != null && authzID.length() > 0) {
+ try {
+ this.authzID = authzID.getBytes("UTF8");
+ } catch (IOException e) {
+ throw new SaslException("Cannot encode authorization ID", e);
+ }
+ }
+ }
+
+ public boolean hasInitialResponse() {
+ return true;
+ }
+
+ /**
+ * Processes the challenge data.
+ *
+ * The server sends a challenge data using which the client must
+ * process using GSS_Init_sec_context.
+ * As per RFC 2222, when GSS_S_COMPLETE is returned, we do
+ * an extra handshake to determine the negotiated security protection
+ * and buffer sizes.
+ *
+ * @param challengeData A non-null byte array containing the
+ * challenge data from the server.
+ * @return A non-null byte array containing the response to be
+ * sent to the server.
+ */
+ public byte[] evaluateChallenge(byte[] challengeData) throws SaslException {
+ if (completed) {
+ throw new IllegalStateException(
+ "GSSAPI authentication already complete");
+ }
+
+ if (finalHandshake) {
+ return doFinalHandshake(challengeData);
+ } else {
+
+ // Security context not established yet; continue with init
+
+ try {
+ byte[] gssOutToken = secCtx.initSecContext(challengeData,
+ 0, challengeData.length);
+ if (logger.isLoggable(Level.FINER)) {
+ traceOutput(MY_CLASS_NAME, "evaluteChallenge",
+ "KRB5CLNT02:Challenge: [raw]", challengeData);
+ traceOutput(MY_CLASS_NAME, "evaluateChallenge",
+ "KRB5CLNT03:Response: [after initSecCtx]", gssOutToken);
+ }
+
+ if (secCtx.isEstablished()) {
+ finalHandshake = true;
+ if (gssOutToken == null) {
+ // RFC 2222 7.2.1: Client responds with no data
+ return EMPTY;
+ }
+ }
+
+ return gssOutToken;
+ } catch (GSSException e) {
+ throw new SaslException("GSS initiate failed", e);
+ }
+ }
+ }
+
+ private byte[] doFinalHandshake(byte[] challengeData) throws SaslException {
+ try {
+ // Security context already established. challengeData
+ // should contain security layers and server's maximum buffer size
+
+ if (logger.isLoggable(Level.FINER)) {
+ traceOutput(MY_CLASS_NAME, "doFinalHandshake",
+ "KRB5CLNT04:Challenge [raw]:", challengeData);
+ }
+
+ if (challengeData.length == 0) {
+ // Received S0, should return []
+ return EMPTY;
+ }
+
+ // Received S1 (security layer, server max recv size)
+
+ byte[] gssOutToken = secCtx.unwrap(challengeData, 0,
+ challengeData.length, new MessageProp(0, false));
+
+ // First octet is a bit-mask specifying the protections
+ // supported by the server
+ if (logger.isLoggable(Level.FINE)) {
+ if (logger.isLoggable(Level.FINER)) {
+ traceOutput(MY_CLASS_NAME, "doFinalHandshake",
+ "KRB5CLNT05:Challenge [unwrapped]:", gssOutToken);
+ }
+ logger.log(Level.FINE, "KRB5CLNT06:Server protections: {0}",
+ gssOutToken[0]);
+ }
+
+ // Client selects preferred protection
+ // qop is ordered list of qop values
+ byte selectedQop = findPreferredMask(gssOutToken[0], qop);
+ if (selectedQop == 0) {
+ throw new SaslException(
+ "No common protection layer between client and server");
+ }
+
+ if ((selectedQop&PRIVACY_PROTECTION) != 0) {
+ privacy = true;
+ integrity = true;
+ } else if ((selectedQop&INTEGRITY_ONLY_PROTECTION) != 0) {
+ integrity = true;
+ }
+
+ // 2nd-4th octets specifies maximum buffer size expected by
+ // server (in network byte order)
+ int srvMaxBufSize = networkByteOrderToInt(gssOutToken, 1, 3);
+
+ // Determine the max send buffer size based on what the
+ // server is able to receive and our specified max
+ sendMaxBufSize = (sendMaxBufSize == 0) ? srvMaxBufSize :
+ Math.min(sendMaxBufSize, srvMaxBufSize);
+
+ // Update context to limit size of returned buffer
+ rawSendSize = secCtx.getWrapSizeLimit(JGSS_QOP, privacy,
+ sendMaxBufSize);
+
+ if (logger.isLoggable(Level.FINE)) {
+ logger.log(Level.FINE,
+"KRB5CLNT07:Client max recv size: {0}; server max recv size: {1}; rawSendSize: {2}",
+ new Object[] {recvMaxBufSize,
+ srvMaxBufSize,
+ rawSendSize});
+ }
+
+ // Construct negotiated security layers and client's max
+ // receive buffer size and authzID
+ int len = 4;
+ if (authzID != null) {
+ len += authzID.length;
+ }
+
+ byte[] gssInToken = new byte[len];
+ gssInToken[0] = selectedQop;
+
+ if (logger.isLoggable(Level.FINE)) {
+ logger.log(Level.FINE,
+ "KRB5CLNT08:Selected protection: {0}; privacy: {1}; integrity: {2}",
+ new Object[]{selectedQop,
+ Boolean.valueOf(privacy),
+ Boolean.valueOf(integrity)});
+ }
+
+ intToNetworkByteOrder(recvMaxBufSize, gssInToken, 1, 3);
+ if (authzID != null) {
+ // copy authorization id
+ System.arraycopy(authzID, 0, gssInToken, 4, authzID.length);
+ logger.log(Level.FINE, "KRB5CLNT09:Authzid: {0}", authzID);
+ }
+
+ if (logger.isLoggable(Level.FINER)) {
+ traceOutput(MY_CLASS_NAME, "doFinalHandshake",
+ "KRB5CLNT10:Response [raw]", gssInToken);
+ }
+
+ gssOutToken = secCtx.wrap(gssInToken,
+ 0, gssInToken.length,
+ new MessageProp(0 /* qop */, false /* privacy */));
+
+ if (logger.isLoggable(Level.FINER)) {
+ traceOutput(MY_CLASS_NAME, "doFinalHandshake",
+ "KRB5CLNT11:Response [after wrap]", gssOutToken);
+ }
+
+ completed = true; // server authenticated
+
+ return gssOutToken;
+ } catch (GSSException e) {
+ throw new SaslException("Final handshake failed", e);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Server.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.security.sasl.gsskerb;
+
+import javax.security.sasl.*;
+import java.io.*;
+import java.util.Map;
+import java.util.logging.Level;
+
+// JAAS
+import javax.security.auth.callback.*;
+
+// JGSS
+import org.ietf.jgss.*;
+
+/**
+ * Implements the GSSAPI SASL server mechanism for Kerberos V5.
+ * (<A HREF="http://www.ietf.org/rfc/rfc2222.txt">RFC 2222</A>,
+ * <a HREF="http://www.ietf.org/internet-drafts/draft-ietf-cat-sasl-gssapi-00.txt">draft-ietf-cat-sasl-gssapi-00.txt</a>).
+ *
+ * Expects thread's Subject to contain server's Kerberos credentials
+ * - If not, underlying KRB5 mech will attempt to acquire Kerberos creds
+ * by logging into Kerberos (via default TextCallbackHandler).
+ * - These creds will be used for exchange with client.
+ *
+ * Required callbacks:
+ * - AuthorizeCallback
+ * handler must verify that authid/authzids are allowed and set
+ * authorized ID to be the canonicalized authzid (if applicable).
+ *
+ * Environment properties that affect behavior of implementation:
+ *
+ * javax.security.sasl.qop
+ * - quality of protection; list of auth, auth-int, auth-conf; default is "auth"
+ * javax.security.sasl.maxbuf
+ * - max receive buffer size; default is 65536
+ * javax.security.sasl.sendmaxbuffer
+ * - max send buffer size; default is 65536; (min with client max recv size)
+ *
+ * @author Rosanna Lee
+ */
+final class GssKrb5Server extends GssKrb5Base implements SaslServer {
+ private static final String MY_CLASS_NAME = GssKrb5Server.class.getName();
+
+ private int handshakeStage = 0;
+ private String peer;
+ private String me;
+ private String authzid;
+ private CallbackHandler cbh;
+
+ // When serverName is null, the server will be unbound. We need to save and
+ // check the protocol name after the context is established. This value
+ // will be null if serverName is not null.
+ private final String protocolSaved;
+ /**
+ * Creates a SASL mechanism with server credentials that it needs
+ * to participate in GSS-API/Kerberos v5 authentication exchange
+ * with the client.
+ */
+ GssKrb5Server(String protocol, String serverName,
+ Map<String, ?> props, CallbackHandler cbh) throws SaslException {
+
+ super(props, MY_CLASS_NAME);
+
+ this.cbh = cbh;
+
+ String service;
+ if (serverName == null) {
+ protocolSaved = protocol;
+ service = null;
+ } else {
+ protocolSaved = null;
+ service = protocol + "@" + serverName;
+ }
+
+ logger.log(Level.FINE, "KRB5SRV01:Using service name: {0}", service);
+
+ try {
+ GSSManager mgr = GSSManager.getInstance();
+
+ // Create the name for the requested service entity for Krb5 mech
+ GSSName serviceName = service == null ? null:
+ mgr.createName(service, GSSName.NT_HOSTBASED_SERVICE, KRB5_OID);
+
+ GSSCredential cred = mgr.createCredential(serviceName,
+ GSSCredential.INDEFINITE_LIFETIME,
+ KRB5_OID, GSSCredential.ACCEPT_ONLY);
+
+ // Create a context using the server's credentials
+ secCtx = mgr.createContext(cred);
+
+ if ((allQop&INTEGRITY_ONLY_PROTECTION) != 0) {
+ // Might need integrity
+ secCtx.requestInteg(true);
+ }
+
+ if ((allQop&PRIVACY_PROTECTION) != 0) {
+ // Might need privacy
+ secCtx.requestConf(true);
+ }
+ } catch (GSSException e) {
+ throw new SaslException("Failure to initialize security context", e);
+ }
+ logger.log(Level.FINE, "KRB5SRV02:Initialization complete");
+ }
+
+
+ /**
+ * Processes the response data.
+ *
+ * The client sends response data to which the server must
+ * process using GSS_accept_sec_context.
+ * As per RFC 2222, the GSS authenication completes (GSS_S_COMPLETE)
+ * we do an extra hand shake to determine the negotiated security protection
+ * and buffer sizes.
+ *
+ * @param responseData A non-null but possible empty byte array containing the
+ * response data from the client.
+ * @return A non-null byte array containing the challenge to be
+ * sent to the client, or null when no more data is to be sent.
+ */
+ public byte[] evaluateResponse(byte[] responseData) throws SaslException {
+ if (completed) {
+ throw new SaslException(
+ "SASL authentication already complete");
+ }
+
+ if (logger.isLoggable(Level.FINER)) {
+ traceOutput(MY_CLASS_NAME, "evaluateResponse",
+ "KRB5SRV03:Response [raw]:", responseData);
+ }
+
+ switch (handshakeStage) {
+ case 1:
+ return doHandshake1(responseData);
+
+ case 2:
+ return doHandshake2(responseData);
+
+ default:
+ // Security context not established yet; continue with accept
+
+ try {
+ byte[] gssOutToken = secCtx.acceptSecContext(responseData,
+ 0, responseData.length);
+
+ if (logger.isLoggable(Level.FINER)) {
+ traceOutput(MY_CLASS_NAME, "evaluateResponse",
+ "KRB5SRV04:Challenge: [after acceptSecCtx]", gssOutToken);
+ }
+
+ if (secCtx.isEstablished()) {
+ handshakeStage = 1;
+
+ peer = secCtx.getSrcName().toString();
+ me = secCtx.getTargName().toString();
+
+ logger.log(Level.FINE,
+ "KRB5SRV05:Peer name is : {0}, my name is : {1}",
+ new Object[]{peer, me});
+
+ // me might take the form of proto@host or proto/host
+ if (protocolSaved != null &&
+ !protocolSaved.equalsIgnoreCase(me.split("[/@]")[0])) {
+ throw new SaslException(
+ "GSS context targ name protocol error: " + me);
+ }
+
+ if (gssOutToken == null) {
+ return doHandshake1(EMPTY);
+ }
+ }
+
+ return gssOutToken;
+ } catch (GSSException e) {
+ throw new SaslException("GSS initiate failed", e);
+ }
+ }
+ }
+
+ private byte[] doHandshake1(byte[] responseData) throws SaslException {
+ try {
+ // Security context already established. responseData
+ // should contain no data
+ if (responseData != null && responseData.length > 0) {
+ throw new SaslException(
+ "Handshake expecting no response data from server");
+ }
+
+ // Construct 4 octets of data:
+ // First octet contains bitmask specifying protections supported
+ // 2nd-4th octets contains max receive buffer of server
+
+ byte[] gssInToken = new byte[4];
+ gssInToken[0] = allQop;
+ intToNetworkByteOrder(recvMaxBufSize, gssInToken, 1, 3);
+
+ if (logger.isLoggable(Level.FINE)) {
+ logger.log(Level.FINE,
+ "KRB5SRV06:Supported protections: {0}; recv max buf size: {1}",
+ new Object[]{allQop,
+ recvMaxBufSize});
+ }
+
+ handshakeStage = 2; // progress to next stage
+
+ if (logger.isLoggable(Level.FINER)) {
+ traceOutput(MY_CLASS_NAME, "doHandshake1",
+ "KRB5SRV07:Challenge [raw]", gssInToken);
+ }
+
+ byte[] gssOutToken = secCtx.wrap(gssInToken, 0, gssInToken.length,
+ new MessageProp(0 /* gop */, false /* privacy */));
+
+ if (logger.isLoggable(Level.FINER)) {
+ traceOutput(MY_CLASS_NAME, "doHandshake1",
+ "KRB5SRV08:Challenge [after wrap]", gssOutToken);
+ }
+ return gssOutToken;
+
+ } catch (GSSException e) {
+ throw new SaslException("Problem wrapping handshake1", e);
+ }
+ }
+
+ private byte[] doHandshake2(byte[] responseData) throws SaslException {
+ try {
+ // Expecting 4 octets from client selected protection
+ // and client's receive buffer size
+ byte[] gssOutToken = secCtx.unwrap(responseData, 0,
+ responseData.length, new MessageProp(0, false));
+
+ if (logger.isLoggable(Level.FINER)) {
+ traceOutput(MY_CLASS_NAME, "doHandshake2",
+ "KRB5SRV09:Response [after unwrap]", gssOutToken);
+ }
+
+ // First octet is a bit-mask specifying the selected protection
+ byte selectedQop = gssOutToken[0];
+ if ((selectedQop&allQop) == 0) {
+ throw new SaslException("Client selected unsupported protection: "
+ + selectedQop);
+ }
+ if ((selectedQop&PRIVACY_PROTECTION) != 0) {
+ privacy = true;
+ integrity = true;
+ } else if ((selectedQop&INTEGRITY_ONLY_PROTECTION) != 0) {
+ integrity = true;
+ }
+
+ // 2nd-4th octets specifies maximum buffer size expected by
+ // client (in network byte order). This is the server's send
+ // buffer maximum.
+ int clntMaxBufSize = networkByteOrderToInt(gssOutToken, 1, 3);
+
+ // Determine the max send buffer size based on what the
+ // client is able to receive and our specified max
+ sendMaxBufSize = (sendMaxBufSize == 0) ? clntMaxBufSize :
+ Math.min(sendMaxBufSize, clntMaxBufSize);
+
+ // Update context to limit size of returned buffer
+ rawSendSize = secCtx.getWrapSizeLimit(JGSS_QOP, privacy,
+ sendMaxBufSize);
+
+ if (logger.isLoggable(Level.FINE)) {
+ logger.log(Level.FINE,
+ "KRB5SRV10:Selected protection: {0}; privacy: {1}; integrity: {2}",
+ new Object[]{selectedQop,
+ Boolean.valueOf(privacy),
+ Boolean.valueOf(integrity)});
+ logger.log(Level.FINE,
+"KRB5SRV11:Client max recv size: {0}; server max send size: {1}; rawSendSize: {2}",
+ new Object[] {clntMaxBufSize,
+ sendMaxBufSize,
+ rawSendSize});
+ }
+
+ // Get authorization identity, if any
+ if (gssOutToken.length > 4) {
+ try {
+ authzid = new String(gssOutToken, 4,
+ gssOutToken.length - 4, "UTF-8");
+ } catch (UnsupportedEncodingException uee) {
+ throw new SaslException ("Cannot decode authzid", uee);
+ }
+ } else {
+ authzid = peer;
+ }
+ logger.log(Level.FINE, "KRB5SRV12:Authzid: {0}", authzid);
+
+ AuthorizeCallback acb = new AuthorizeCallback(peer, authzid);
+
+ // In Kerberos, realm is embedded in peer name
+ cbh.handle(new Callback[] {acb});
+ if (acb.isAuthorized()) {
+ authzid = acb.getAuthorizedID();
+ completed = true;
+ } else {
+ // Authorization failed
+ throw new SaslException(peer +
+ " is not authorized to connect as " + authzid);
+ }
+
+ return null;
+ } catch (GSSException e) {
+ throw new SaslException("Final handshake step failed", e);
+ } catch (IOException e) {
+ throw new SaslException("Problem with callback handler", e);
+ } catch (UnsupportedCallbackException e) {
+ throw new SaslException("Problem with callback handler", e);
+ }
+ }
+
+ public String getAuthorizationID() {
+ if (completed) {
+ return authzid;
+ } else {
+ throw new IllegalStateException("Authentication incomplete");
+ }
+ }
+
+ public Object getNegotiatedProperty(String propName) {
+ if (!completed) {
+ throw new IllegalStateException("Authentication incomplete");
+ }
+
+ Object result;
+ switch (propName) {
+ case Sasl.BOUND_SERVER_NAME:
+ try {
+ // me might take the form of proto@host or proto/host
+ result = me.split("[/@]")[1];
+ } catch (Exception e) {
+ result = null;
+ }
+ break;
+ default:
+ result = super.getNegotiatedProperty(propName);
+ }
+ return result;
+ }
+}
--- a/jdk/test/ProblemList.txt Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/ProblemList.txt Wed Jul 05 20:01:44 2017 +0200
@@ -139,9 +139,6 @@
com/sun/management/OperatingSystemMXBean/GetSystemCpuLoad.java aix-all
javax/management/MBeanServer/OldMBeanServerTest.java aix-all
-# 8050115
-javax/management/monitor/GaugeMonitorDeadlockTest.java generic-all
-
############################################################################
# jdk_math
--- a/jdk/test/TEST.ROOT Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/TEST.ROOT Wed Jul 05 20:01:44 2017 +0200
@@ -8,7 +8,7 @@
othervm.dirs=java/awt java/beans javax/accessibility javax/imageio javax/sound javax/print javax/management com/sun/awt sun/awt sun/java2d sun/pisces
# Tests that cannot run concurrently
-exclusiveAccess.dirs=java/rmi/Naming java/util/prefs sun/management/jmxremote sun/tools/jstatd sun/security/mscapi
+exclusiveAccess.dirs=java/rmi/Naming java/util/prefs sun/management/jmxremote sun/tools/jstatd sun/security/mscapi java/util/stream
# Group definitions
groups=TEST.groups [closed/TEST.groups]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Graphics2D/WhiteTextColorTest.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2014, 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.*;
+import java.awt.image.*;
+import javax.swing.*;
+
+/**
+ * @test
+ * @bug 8056009
+ * @summary tests whether Graphics.setColor-calls with Color.white are ignored directly
+ * after pipeline initialization for a certain set of operations.
+ * @author ceisserer
+ */
+public class WhiteTextColorTest extends Frame {
+ public static volatile boolean success = false;
+
+ public WhiteTextColorTest() {
+ Image dstImg = getGraphicsConfiguration()
+ .createCompatibleVolatileImage(30, 20);
+ Graphics g = dstImg.getGraphics();
+
+ g.setColor(Color.BLACK);
+ g.fillRect(0, 0, dstImg.getWidth(null), dstImg.getHeight(null));
+ g.setColor(Color.WHITE);
+ g.drawString("Test", 0, 15);
+
+ BufferedImage readBackImg = new BufferedImage(dstImg.getWidth(null),
+ dstImg.getHeight(null), BufferedImage.TYPE_INT_RGB);
+ readBackImg.getGraphics().drawImage(dstImg, 0, 0, null);
+
+ for (int x = 0; x < readBackImg.getWidth(); x++) {
+ for (int y = 0; y < readBackImg.getHeight(); y++) {
+ int pixel = readBackImg.getRGB(x, y);
+
+ // In case a single white pixel is found, the
+ // setColor(Color.WHITE)
+ // call before was not ignored and the bug is not present
+ if (pixel == 0xFFFFFFFF) {
+ return;
+ }
+ }
+ }
+
+ throw new RuntimeException("Test Failed");
+ }
+
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ new WhiteTextColorTest();
+ }
+ });
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Window/setLocRelativeTo/SetLocationRelativeToTest.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2014, 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.*;
+import java.util.ArrayList;
+import javax.swing.*;
+
+/*
+@test
+@summary Toplevel should be correctly positioned as relative to a component:
+ so that their centers coincide
+ or, if the component is hidden, centered on the screen.
+@bug 8036915
+@library ../../../../lib/testlibrary
+@build ExtendedRobot
+@run main/timeout=1200 SetLocationRelativeToTest
+*/
+
+public class SetLocationRelativeToTest {
+ private static int delay = 500;
+ private static boolean testEverything = false;// NB: change this to true to test everything
+ java.util.List<Window> awtToplevels = new ArrayList<Window>();
+ java.util.List<Window> swingToplevels = new ArrayList<Window>();
+ java.util.List<Window> allToplevels = new ArrayList<Window>();
+ java.util.List<Component> awtComponents = new ArrayList<Component>();
+ java.util.List<Component> swingComponents = new ArrayList<Component>();
+ java.util.List<Component> allComponents = new ArrayList<Component>();
+ Label placeholder = new Label();
+ JLabel jplaceholder = new JLabel();
+ JFrame jcontainer;
+ public SetLocationRelativeToTest() {
+ Frame frame = new Frame("Frame");
+ frame.setSize(200,100);
+ Frame uframe = new Frame("U.Frame");
+ uframe.setUndecorated(true);
+ uframe.setSize(200,100);
+ Window window = new Window(frame);
+ window.setSize(200,100);
+ Dialog dialog = new Dialog(frame, "Dialog");
+ dialog.setSize(200,100);
+ awtToplevels.add(frame);
+ awtToplevels.add(uframe);
+ awtToplevels.add(window);
+ awtToplevels.add(dialog);
+
+ awtComponents.add(new TextArea("Am a TextArea"));
+ awtComponents.add(new TextField("Am a TextField"));
+ awtComponents.add(new Button("Press"));
+ awtComponents.add(new Label("Label"));
+ Choice aChoice = new Choice();
+ aChoice.add("One");
+ aChoice.add("Two");
+ awtComponents.add(aChoice);
+ awtComponents.add(new Canvas());
+ awtComponents.add(new List(4));
+ awtComponents.add(new Checkbox("Me CheckBox"));
+ awtComponents.add(new Scrollbar());
+
+ swingComponents.add(new JTextArea("Am a JTextArea"));
+ swingComponents.add(new JTextField("Am a JTextField"));
+ swingComponents.add(new JButton("Press"));
+ swingComponents.add(new JLabel("JLabel"));
+ JComboBox jcombo = new JComboBox();
+ swingComponents.add(jcombo);
+ swingComponents.add(new JPanel());
+ swingComponents.add(new JList());
+ swingComponents.add(new JCheckBox("Me JCheckBox"));
+ swingComponents.add(new JScrollBar());
+ }
+
+ public static void main(String args[]) {
+ SetLocationRelativeToTest test = new SetLocationRelativeToTest();
+ test.doAWTTest(true);
+ test.doAWTTest(false);
+ try {
+ test.doSwingTest(true);
+ test.doSwingTest(false);
+ }catch(InterruptedException ie) {
+ ie.printStackTrace();
+ }catch(java.lang.reflect.InvocationTargetException ite) {
+ ite.printStackTrace();
+ throw new RuntimeException("InvocationTarget?");
+ }
+ return;
+ }
+
+ // In regular testing, we select just few components to test
+ // randomly. If full testing required, select many ("all").
+ void selectObjectsToTest(boolean doSwing) {
+ allToplevels.clear();
+ allComponents.clear();
+ if(testEverything) {
+ allToplevels.addAll(0, awtToplevels);
+ allComponents.addAll(0, awtComponents);
+ if(doSwing) {
+ allToplevels.addAll(allToplevels.size(), swingToplevels);
+ allComponents.addAll(allComponents.size(), swingComponents);
+ }
+ }else{
+ //select a random of each
+ int i = (int)(java.lang.Math.random()*awtToplevels.size());
+ allToplevels.add(awtToplevels.get(i));
+ i = (int)(java.lang.Math.random()*awtComponents.size());
+ allComponents.add(awtComponents.get(i));
+ if(doSwing) {
+ i = (int)(java.lang.Math.random()*swingToplevels.size());
+ allToplevels.add(swingToplevels.get(i));
+ i = (int)(java.lang.Math.random()*swingComponents.size());
+ allComponents.add(swingComponents.get(i));
+ }
+ }
+ }
+
+ // create Frame, add an AWT component to it,
+ // hide it (or not) and position a new toplevel
+ // relativeTo
+ void doAWTTest(boolean isHidden) {
+ boolean res;
+ ExtendedRobot robot;
+ try {
+ robot = new ExtendedRobot();
+ }catch(Exception ex) {
+ ex.printStackTrace();
+ throw new RuntimeException("Failed: "+ex.getMessage());
+ }
+ Frame container = new Frame("Frame");
+ container.setBounds(100,100,300,300);
+ container.setLayout(new GridLayout(3,1));
+ container.add(placeholder);
+ container.setVisible(true);
+ selectObjectsToTest(false);
+ for(Component c: allComponents) {
+ placeholder.setText((isHidden ? "Hidden: " : "Below is ")+ c.getClass().getName());
+ c.setVisible(true);
+ container.add(c);
+ container.doLayout();
+ if(isHidden) {
+ c.setVisible(false);
+ }
+ robot.waitForIdle(delay);
+ for(Window w: allToplevels) {
+ w.setLocationRelativeTo(c);
+ w.setVisible(true);
+ robot.waitForIdle(delay);
+ res = compareLocations(w, c, robot);
+ System.out.println(c.getClass().getName()+" \t: "+w.getClass().getName()+
+ ((w instanceof Frame) && (((Frame)w).isUndecorated()) ? " undec\t\t:" : "\t\t:")+" "+
+ (res ? "" : "Failed"));
+ if(!res) {
+ throw new RuntimeException("Test failed.");
+ }
+ w.dispose();
+ }
+ container.remove(c);
+ robot.waitForIdle(delay);
+ }
+ container.dispose();
+ }
+
+ // Create JFrame, add an AWT or Swing component to it,
+ // hide it (or not) and position a new toplevel
+ // relativeTo
+ void doSwingTest(boolean isHidden) throws InterruptedException,
+ java.lang.reflect.InvocationTargetException {
+ boolean res;
+ ExtendedRobot robot;
+ try {
+ robot = new ExtendedRobot();
+ }catch(Exception ex) {
+ ex.printStackTrace();
+ throw new RuntimeException("Failed: "+ex.getMessage());
+ }
+
+ EventQueue.invokeAndWait( () -> {
+ JFrame jframe = new JFrame("jframe");
+ jframe.setSize(200,100);
+ swingToplevels.add(jframe);
+ JFrame ujframe = new JFrame("ujframe");
+ ujframe.setSize(200,100);
+ ujframe.setUndecorated(true);
+ swingToplevels.add(ujframe);
+ JWindow jwin = new JWindow();
+ jwin.setSize(200,100);
+ swingToplevels.add(jwin);
+ JDialog jdia = new JDialog((Frame)null, "JDialog");
+ jdia.setSize(200,100);
+ swingToplevels.add(jdia);
+ jcontainer = new JFrame("JFrame");
+ jcontainer.setBounds(100,100,300,300);
+ jcontainer.setLayout(new GridLayout(3,1));
+ jcontainer.add(jplaceholder);
+ jcontainer.setVisible(true);
+ selectObjectsToTest(true);
+ });
+ robot.waitForIdle(delay);
+
+ for(Component c: allComponents) {
+ EventQueue.invokeAndWait( () -> {
+ jplaceholder.setText((isHidden ? "Hidden: " : "Below is: ")+ c.getClass().getName());
+ c.setVisible(true);
+ jcontainer.add(c);
+ jcontainer.doLayout();
+ if(isHidden) {
+ c.setVisible(false);
+ }
+ });
+ robot.waitForIdle(delay);
+ for(Window w: allToplevels) {
+ EventQueue.invokeAndWait( () -> {
+ w.setLocationRelativeTo(c);
+ w.setVisible(true);
+ });
+ robot.waitForIdle(delay);
+ res = compareLocations(w, c, robot);
+ System.out.println(c.getClass().getName()+" \t: "+w.getClass().getName()+
+ ((w instanceof Frame) && (((Frame)w).isUndecorated()) ? " undec\t\t:" : "\t\t:")+" "+
+ (res ? "" : "Failed"));
+ EventQueue.invokeAndWait( () -> {
+ w.dispose();
+ });
+ robot.waitForIdle();
+ if(!res) {
+ throw new RuntimeException("Test failed.");
+ }
+ }
+ EventQueue.invokeAndWait( () -> {
+ jcontainer.remove(c);
+ });
+ robot.waitForIdle(delay);
+ }
+ EventQueue.invokeAndWait( () -> {
+ jcontainer.dispose();
+ });
+ }
+
+ // Check, finally, if w either is concentric with c
+ // or sits in the center of the screen (if c is hidden)
+ boolean compareLocations(final Window w, final Component c, ExtendedRobot robot) {
+ final Point pc = new Point();
+ final Point pw = new Point();
+ try {
+ EventQueue.invokeAndWait( () -> {
+ pw.setLocation(w.getLocationOnScreen());
+ pw.translate(w.getWidth()/2, w.getHeight()/2);
+ if(!c.isVisible()) {
+ Rectangle screenRect = w.getGraphicsConfiguration().getBounds();
+ pc.setLocation(screenRect.x+screenRect.width/2,
+ screenRect.y+screenRect.height/2);
+ }else{
+ pc.setLocation(c.getLocationOnScreen());
+ pc.translate(c.getWidth()/2, c.getHeight()/2);
+ }
+ });
+ } catch(InterruptedException ie) {
+ throw new RuntimeException("Interrupted");
+ } catch(java.lang.reflect.InvocationTargetException ite) {
+ ite.printStackTrace();
+ throw new RuntimeException("InvocationTarget?");
+ }
+ robot.waitForIdle(delay);
+ // Compare with 1 tolerance to forgive possible rounding errors
+ if(pc.x - pw.x > 1 ||
+ pc.x - pw.x < -1 ||
+ pc.y - pw.y > 1 ||
+ pc.y - pw.y < -1 ) {
+ System.out.println("Center of "+(c.isVisible() ? "Component:" : "screen:")+pc);
+ System.out.println("Center of Window:"+pw);
+ System.out.println("Centers of "+w+" and "+c+" do not coincide");
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/font/GlyphVector/GlyphVectorOutline.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2014 Google Inc. 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.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.font.LineBreakMeasurer;
+import java.awt.font.TextAttribute;
+import java.awt.font.TextLayout;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.text.AttributedString;
+
+import javax.imageio.ImageIO;
+
+/**
+ * Manual test for:
+ * JDK-8057986: freetype code to get glyph outline does not handle initial control point properly
+ *
+ * Manual repro recipe:
+ * (cd test/java/awt/font/GlyphVector/ && javac GlyphVectorOutline.java && wget -q -O/tmp/msgothic.ttc https://browserlinux-jp.googlecode.com/files/msgothic.ttc && java GlyphVectorOutline /tmp/msgothic.ttc /tmp/katakana.png)
+ *
+ * Then examine the two rendered Japanese characters in the png file.
+ *
+ * Renders text to a PNG by
+ * 1. using the native Graphics2D#drawGlyphVector implementation
+ * 2. filling in the result of GlyphVector#getOutline
+ *
+ * Should be the same but is different for some CJK characters
+ * (e.g. Katakana character \u30AF).
+ *
+ * @author ikopylov@google.com (Igor Kopylov)
+ */
+public class GlyphVectorOutline {
+ public static void main(String[] args) throws Exception {
+ if (args.length != 2) {
+ throw new Error("Usage: java GlyphVectorOutline fontfile outputfile");
+ }
+ writeImage(new File(args[0]),
+ new File(args[1]),
+ "\u30AF");
+ }
+
+ public static void writeImage(File fontFile, File outputFile, String value) throws Exception {
+ BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g = image.createGraphics();
+ g.setColor(Color.WHITE);
+ g.fillRect(0, 0, image.getWidth(), image.getHeight());
+ g.setColor(Color.BLACK);
+
+ Font font = Font.createFont(Font.TRUETYPE_FONT, fontFile);
+ font = font.deriveFont(Font.PLAIN, 72f);
+ FontRenderContext frc = new FontRenderContext(null, false, false);
+ GlyphVector gv = font.createGlyphVector(frc, value);
+ g.drawGlyphVector(gv, 10, 80);
+ g.fill(gv.getOutline(10, 180));
+ ImageIO.write(image, "png", outputFile);
+ }
+
+ private static void drawString(Graphics2D g, Font font, String value, float x, float y) {
+ AttributedString str = new AttributedString(value);
+ str.addAttribute(TextAttribute.FOREGROUND, Color.BLACK);
+ str.addAttribute(TextAttribute.FONT, font);
+ FontRenderContext frc = new FontRenderContext(null, true, true);
+ TextLayout layout = new LineBreakMeasurer(str.getIterator(), frc).nextLayout(Integer.MAX_VALUE);
+ layout.draw(g, x, y);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/LFCaching/LFCachingTestCase.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, 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.lang.invoke.MethodHandle;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Abstract class for lambda forms caching testing.
+ *
+ * @author kshefov
+ */
+public abstract class LFCachingTestCase extends LambdaFormTestCase {
+
+ /**
+ * Constructor for lambda forms caching test case.
+ *
+ * @param testMethod A method from {@code j.l.i.MethodHandles} class that
+ * returns a {@code j.l.i.MethodHandle} instance.
+ */
+ protected LFCachingTestCase(TestMethods testMethod) {
+ super(testMethod);
+ }
+
+ /**
+ * Checks that the lambda forms of the two adapter method handles adapter1
+ * and adapter2 are the same.
+ *
+ * @param adapter1 First method handle.
+ * @param adapter2 Second method handle.
+ */
+ public void checkLFCaching(MethodHandle adapter1, MethodHandle adapter2) {
+ try {
+
+ if (!adapter1.type().equals(adapter2.type())) {
+ throw new Error("TESTBUG: Types of the two method handles are not the same");
+ }
+
+ Object lambdaForm0 = LambdaFormTestCase.INTERNAL_FORM.invoke(adapter1);
+ Object lambdaForm1 = LambdaFormTestCase.INTERNAL_FORM.invoke(adapter2);
+
+ if (lambdaForm0 == null || lambdaForm1 == null) {
+ throw new Error("Unexpected error: One or both lambda forms of the method handles are null");
+ }
+
+ if (lambdaForm0 != lambdaForm1) {
+ System.err.println("Lambda form 0 toString is:");
+ System.err.println(lambdaForm0);
+ System.err.println("Lambda form 1 toString is:");
+ System.err.println(lambdaForm1);
+ throw new AssertionError("Error: Lambda forms of the two method handles"
+ + " are not the same. LF cahing does not work");
+ }
+ } catch (IllegalAccessException | IllegalArgumentException |
+ SecurityException | InvocationTargetException ex) {
+ throw new Error("Unexpected exception: ", ex);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2014, 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 LFGarbageCollectedTest
+ * @bug 8046703
+ * @summary Test verifies that lambda forms are garbage collected
+ * @author kshefov
+ * @ignore 8057020
+ * @library /lib/testlibrary/jsr292 /lib/testlibrary
+ * @build TestMethods
+ * @build LambdaFormTestCase
+ * @build LFGarbageCollectedTest
+ * @run main/othervm/timeout=600 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true -DtestLimit=150 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI LFGarbageCollectedTest
+ */
+
+import java.lang.invoke.MethodHandle;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.Map;
+
+/**
+ * Lambda forms garbage collection test class.
+ */
+public final class LFGarbageCollectedTest extends LambdaFormTestCase {
+
+ /**
+ * Constructor for a lambda forms garbage collection test case.
+ *
+ * @param testMethod A method from {@code j.l.i.MethodHandles} class that
+ * returns a {@code j.l.i.MethodHandle} instance.
+ */
+ public LFGarbageCollectedTest(TestMethods testMethod) {
+ super(testMethod);
+ }
+
+ @Override
+ public void doTest() {
+ try {
+ Map<String, Object> data = getTestMethod().getTestCaseData();
+ MethodHandle adapter;
+ try {
+ adapter = getTestMethod().getTestCaseMH(data, TestMethods.Kind.ONE);
+ } catch (NoSuchMethodException ex) {
+ throw new Error("Unexpected exception: ", ex);
+ }
+ Object lambdaForm = LambdaFormTestCase.INTERNAL_FORM.invoke(adapter);
+ if (lambdaForm == null) {
+ throw new Error("Unexpected error: Lambda form of the method handle is null");
+ }
+ ReferenceQueue rq = new ReferenceQueue();
+ PhantomReference ph = new PhantomReference(lambdaForm, rq);
+ lambdaForm = null;
+ data = null;
+ adapter = null;
+ for (int i = 0; i < 1000 && !ph.isEnqueued(); i++) {
+ System.gc();
+ }
+ if (!ph.isEnqueued()) {
+ throw new AssertionError("Error: Lambda form is not garbage collected");
+ }
+ } catch (IllegalAccessException | IllegalArgumentException |
+ InvocationTargetException ex) {
+ throw new Error("Unexpected exception: ", ex);
+ }
+ }
+
+ /**
+ * Main routine for lambda forms garbage collection test.
+ *
+ * @param args Accepts no arguments.
+ */
+ public static void main(String[] args) {
+ // The "identity" and "constant" methods should be removed from this test,
+ // because their lambda forms are stored in a static filed and are not GC'ed.
+ // There can be only 5 such LFs for each method, so no memory leak happens.
+ EnumSet<TestMethods> testMethods = EnumSet.complementOf(EnumSet.of(TestMethods.IDENTITY, TestMethods.CONSTANT));
+ LambdaFormTestCase.runTests(LFGarbageCollectedTest::new, testMethods);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2014, 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 LFMultiThreadCachingTest
+ * @bug 8046703
+ * @summary Test verifies that lambda forms are cached when run with multiple threads
+ * @author kshefov
+ * @library /lib/testlibrary/jsr292 /lib/testlibrary
+ * @build TestMethods
+ * @build LambdaFormTestCase
+ * @build LFCachingTestCase
+ * @build LFMultiThreadCachingTest
+ * @run main/othervm/timeout=300 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true LFMultiThreadCachingTest
+ */
+
+import java.lang.invoke.MethodHandle;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.CyclicBarrier;
+
+/**
+ * Multiple threaded lambda forms caching test class.
+ */
+public final class LFMultiThreadCachingTest extends LFCachingTestCase {
+ private static final TestMethods.Kind[] KINDS;
+ static {
+ EnumSet<TestMethods.Kind> set = EnumSet.complementOf(EnumSet.of(TestMethods.Kind.EXCEPT));
+ KINDS = set.toArray(new TestMethods.Kind[set.size()]);
+ if (KINDS.length < 2) {
+ throw new Error("TESTBUG: KINDS.length[" + KINDS.length + "] should be at least 2");
+ }
+ }
+ private static final int CORES = Math.max(KINDS.length, Runtime.getRuntime().availableProcessors());
+
+ /**
+ * Constructor a for multiple threaded lambda forms caching test case.
+ *
+ * @param testMethod A method from {@code j.l.i.MethodHandles} class that
+ * returns a {@code j.l.i.MethodHandle} instance.
+ */
+ public LFMultiThreadCachingTest(TestMethods testMethod) {
+ super(testMethod);
+ }
+
+ @Override
+ public void doTest() {
+ Map<String, Object> data = getTestMethod().getTestCaseData();
+ ConcurrentLinkedQueue<MethodHandle> adapters = new ConcurrentLinkedQueue<>();
+ CyclicBarrier begin = new CyclicBarrier(CORES);
+ CountDownLatch end = new CountDownLatch(CORES);
+ for (int i = 0; i < CORES; ++i) {
+ TestMethods.Kind kind = KINDS[i % KINDS.length];
+ new Thread(() -> {
+ try {
+ begin.await();
+ adapters.add(getTestMethod().getTestCaseMH(data, kind));
+ } catch (InterruptedException | BrokenBarrierException | IllegalAccessException | NoSuchMethodException ex) {
+ throw new Error("Unexpected exception: ", ex);
+ } finally {
+ end.countDown();
+ }
+ }).start();
+ }
+ try {
+ end.await();
+ } catch (InterruptedException ex) {
+ throw new Error("Unexpected exception: ", ex);
+ }
+ if (adapters.size() < CORES) {
+ throw new Error("adapters size[" + adapters.size() + "] is less than " + CORES);
+ }
+ MethodHandle prev = adapters.poll();
+ for (MethodHandle current : adapters) {
+ checkLFCaching(prev, current);
+ prev = current;
+ }
+ }
+
+ /**
+ * Main routine for multiple threaded lambda forms caching test.
+ *
+ * @param args Accepts no arguments.
+ */
+ public static void main(String[] args) {
+ LambdaFormTestCase.runTests(LFMultiThreadCachingTest::new, EnumSet.allOf(TestMethods.class));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, 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 LFSingleThreadCachingTest
+ * @bug 8046703
+ * @summary Test verifies that lambda forms are cached when run with single thread
+ * @author kshefov
+ * @library /lib/testlibrary/jsr292 /lib/testlibrary
+ * @build TestMethods
+ * @build LambdaFormTestCase
+ * @build LFCachingTestCase
+ * @build LFSingleThreadCachingTest
+ * @run main/othervm/timeout=300 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true LFSingleThreadCachingTest
+ */
+
+import java.lang.invoke.MethodHandle;
+import java.util.EnumSet;
+import java.util.Map;
+
+/**
+ * Single threaded lambda forms caching test class.
+ */
+public final class LFSingleThreadCachingTest extends LFCachingTestCase {
+
+ /**
+ * Constructor for a single threaded lambda forms caching test case.
+ *
+ * @param testMethod A method from {@code j.l.i.MethodHandles} class that
+ * returns a {@code j.l.i.MethodHandle} instance.
+ */
+ public LFSingleThreadCachingTest(TestMethods testMethod) {
+ super(testMethod);
+ }
+
+ @Override
+ public void doTest() {
+ MethodHandle adapter1;
+ MethodHandle adapter2;
+ Map<String, Object> data = getTestMethod().getTestCaseData();
+ try {
+ adapter1 = getTestMethod().getTestCaseMH(data, TestMethods.Kind.ONE);
+ adapter2 = getTestMethod().getTestCaseMH(data, TestMethods.Kind.TWO);
+ } catch (NoSuchMethodException | IllegalAccessException ex) {
+ throw new Error("Unexpected exception: ", ex);
+ }
+ checkLFCaching(adapter1, adapter2);
+ }
+
+ /**
+ * Main routine for single threaded lambda forms caching test.
+ *
+ * @param args Accepts no arguments.
+ */
+ public static void main(String[] args) {
+ LambdaFormTestCase.runTests(LFSingleThreadCachingTest::new, EnumSet.allOf(TestMethods.class));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/LFCaching/LambdaFormTestCase.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2014, 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 com.oracle.testlibrary.jsr292.Helper;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.function.Function;
+
+/**
+ * Lambda forms caching test case class. Contains all necessary test routines to
+ * test lambda forms caching in method handles returned by methods of
+ * MethodHandles class.
+ *
+ * @author kshefov
+ */
+public abstract class LambdaFormTestCase {
+
+ private final static String METHOD_HANDLE_CLASS_NAME = "java.lang.invoke.MethodHandle";
+ private final static String INTERNAL_FORM_METHOD_NAME = "internalForm";
+
+ /**
+ * Reflection link to {@code j.l.i.MethodHandle.internalForm} method. It is
+ * used to get a lambda form from a method handle.
+ */
+ protected final static Method INTERNAL_FORM;
+
+ static {
+ try {
+ Class mhClass = Class.forName(METHOD_HANDLE_CLASS_NAME);
+ INTERNAL_FORM = mhClass.getDeclaredMethod(INTERNAL_FORM_METHOD_NAME);
+ INTERNAL_FORM.setAccessible(true);
+ } catch (Exception ex) {
+ throw new Error("Unexpected exception: ", ex);
+ }
+ }
+
+ private final TestMethods testMethod;
+
+ /**
+ * Test case constructor. Generates test cases with random method types for
+ * given methods form {@code j.l.i.MethodHandles} class.
+ *
+ * @param testMethod A method from {@code j.l.i.MethodHandles} class which
+ * returns a {@code j.l.i.MethodHandle}.
+ */
+ protected LambdaFormTestCase(TestMethods testMethod) {
+ this.testMethod = testMethod;
+ }
+
+ public TestMethods getTestMethod() {
+ return testMethod;
+ }
+
+ /**
+ * Routine that executes a test case.
+ */
+ public abstract void doTest();
+
+ /**
+ * Runs a number of test cases defined by the size of testCases list.
+ *
+ * @param ctor constructor of LambdaFormCachingTest or its child classes
+ * object.
+ * @param testMethods list of test methods
+ */
+ public static void runTests(Function<TestMethods, LambdaFormTestCase> ctor, Collection<TestMethods> testMethods) {
+ boolean passed = true;
+ int testCounter = 0;
+ int failCounter = 0;
+ long iterations = Math.max(1, Helper.TEST_LIMIT / testMethods.size());
+ for (long i = 0; i < iterations; i++) {
+ System.err.println(String.format("Iteration %d:", i));
+ for (TestMethods testMethod : testMethods) {
+ LambdaFormTestCase testCase = ctor.apply(testMethod);
+ try {
+ System.err.printf("Tested LF caching feature with MethodHandles.%s method.%n",
+ testCase.getTestMethod().name);
+ testCase.doTest();
+ System.err.println("PASSED");
+ } catch (Throwable t) {
+ t.printStackTrace();
+ System.err.println("FAILED");
+ passed = false;
+ failCounter++;
+ }
+ testCounter++;
+ }
+ }
+ if (!passed) {
+ throw new Error(String.format("%d of %d test cases FAILED! %n"
+ + "Rerun the test with the same \"-Dseed=\" option as in the log file!",
+ failCounter, testCounter));
+ } else {
+ System.err.println(String.format("All %d test cases PASSED!", testCounter));
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/LFCaching/TestMethods.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,698 @@
+/*
+ * Copyright (c) 2014, 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 com.oracle.testlibrary.jsr292.Helper;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Enumeration containing information about methods from
+ * {@code j.l.i.MethodHandles} class that are used for testing lambda forms
+ * caching.
+ *
+ * @author kshefov
+ */
+public enum TestMethods {
+
+ FOLD_ARGUMENTS("foldArguments") {
+ @Override
+ public Map<String, Object> getTestCaseData() {
+ Map<String, Object> data = new HashMap<>();
+ int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+ MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+ data.put("mtTarget", mtTarget);
+ // Arity after reducing because of long and double take 2 slots.
+ int realArity = mtTarget.parameterCount();
+ int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1);
+ data.put("modifierMHArgNum", modifierMHArgNum);
+ Class<?> combinerReturnType;
+ if (realArity == 0) {
+ combinerReturnType = void.class;
+ } else {
+ combinerReturnType = Helper.RNG.nextBoolean() ? void.class : mtTarget.parameterType(0);
+ }
+ data.put("combinerReturnType", combinerReturnType);
+ return data;
+ }
+
+ @Override
+ protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+ MethodType mtTarget = (MethodType) data.get("mtTarget");
+ Class<?> combinerReturnType = (Class) data.get("combinerReturnType");
+ int modifierMHArgNum = (int) data.get("modifierMHArgNum");
+ MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+ mtTarget.parameterList(), kind);
+ Class<?> rType = mtTarget.returnType();
+ int combListStart = (combinerReturnType == void.class) ? 0 : 1;
+ if (modifierMHArgNum < combListStart) {
+ modifierMHArgNum = combListStart;
+ }
+ MethodHandle combiner = TestMethods.methodHandleGenerator(combinerReturnType,
+ mtTarget.parameterList().subList(combListStart,
+ modifierMHArgNum), kind);
+ return MethodHandles.foldArguments(target, combiner);
+ }
+ },
+ DROP_ARGUMENTS("dropArguments") {
+ @Override
+ public Map<String, Object> getTestCaseData() {
+ Map<String, Object> data = new HashMap<>();
+ int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+ MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+ data.put("mtTarget", mtTarget);
+ // Arity after reducing because of long and double take 2 slots.
+ int realArity = mtTarget.parameterCount();
+ int dropArgsPos = Helper.RNG.nextInt(realArity + 1);
+ data.put("dropArgsPos", dropArgsPos);
+ MethodType mtDropArgs = TestMethods.randomMethodTypeGenerator(
+ Helper.RNG.nextInt(Helper.MAX_ARITY - realArity));
+ data.put("mtDropArgs", mtDropArgs);
+ return data;
+ }
+
+ @Override
+ protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+ MethodType mtTarget = (MethodType) data.get("mtTarget");
+ MethodType mtDropArgs = (MethodType) data.get("mtDropArgs");
+ int dropArgsPos = (int) data.get("dropArgsPos");
+ MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+ mtTarget.parameterList(), kind);
+ int mtTgtSlotsCount = TestMethods.argSlotsCount(mtTarget);
+ int mtDASlotsCount = TestMethods.argSlotsCount(mtDropArgs);
+ List<Class<?>> fakeParList;
+ if (mtTgtSlotsCount + mtDASlotsCount > Helper.MAX_ARITY - 1) {
+ fakeParList = TestMethods.reduceArgListToSlotsCount(mtDropArgs.parameterList(),
+ Helper.MAX_ARITY - mtTgtSlotsCount - 1);
+ } else {
+ fakeParList = mtDropArgs.parameterList();
+ }
+ return MethodHandles.dropArguments(target, dropArgsPos, fakeParList);
+ }
+ },
+ EXPLICIT_CAST_ARGUMENTS("explicitCastArguments") {
+ @Override
+ public Map<String, Object> getTestCaseData() {
+ Map<String, Object> data = new HashMap<>();
+ int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY / 2);
+ MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+ data.put("mtTarget", mtTarget);
+ // Arity after reducing because of long and double take 2 slots.
+ int realArity = mtTarget.parameterCount();
+ MethodType mtExcplCastArgs = TestMethods.randomMethodTypeGenerator(realArity);
+ if (mtTarget.returnType() == void.class) {
+ mtExcplCastArgs = MethodType.methodType(void.class,
+ mtExcplCastArgs.parameterArray());
+ }
+ if (mtExcplCastArgs.returnType() == void.class) {
+ mtExcplCastArgs = MethodType.methodType(mtTarget.returnType(),
+ mtExcplCastArgs.parameterArray());
+ }
+ data.put("mtExcplCastArgs", mtExcplCastArgs);
+ return data;
+ }
+
+ @Override
+ protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+ MethodType mtTarget = (MethodType) data.get("mtTarget");
+ MethodType mtExcplCastArgs = (MethodType) data.get("mtExcplCastArgs");
+ MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+ mtTarget.parameterList(), kind);
+ return MethodHandles.explicitCastArguments(target, mtExcplCastArgs);
+ }
+ },
+ FILTER_ARGUMENTS("filterArguments") {
+ @Override
+ public Map<String, Object> getTestCaseData() {
+ Map<String, Object> data = new HashMap<>();
+ int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY / 2);
+ MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+ data.put("mtTarget", mtTarget);
+ // Arity after reducing because of long and double take 2 slots.
+ int realArity = mtTarget.parameterCount();
+ int filterArgsPos = Helper.RNG.nextInt(realArity + 1);
+ data.put("filterArgsPos", filterArgsPos);
+ int filtersArgsArrayLength = Helper.RNG.nextInt(realArity + 1 - filterArgsPos);
+ data.put("filtersArgsArrayLength", filtersArgsArrayLength);
+ MethodType mtFilter = TestMethods.randomMethodTypeGenerator(filtersArgsArrayLength);
+ data.put("mtFilter", mtFilter);
+ return data;
+ }
+
+ @Override
+ protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+ MethodType mtTarget = (MethodType) data.get("mtTarget");
+ MethodType mtFilter = (MethodType) data.get("mtFilter");
+ int filterArgsPos = (int) data.get("filterArgsPos");
+ int filtersArgsArrayLength = (int) data.get("filtersArgsArrayLength");
+ MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+ mtTarget.parameterList(), kind);
+ MethodHandle[] filters = new MethodHandle[filtersArgsArrayLength];
+ for (int i = 0; i < filtersArgsArrayLength; i++) {
+ filters[i] = TestMethods.filterGenerator(mtFilter.parameterType(i),
+ mtTarget.parameterType(filterArgsPos + i), kind);
+ }
+ return MethodHandles.filterArguments(target, filterArgsPos, filters);
+ }
+ },
+ FILTER_RETURN_VALUE("filterReturnValue") {
+ @Override
+ public Map<String, Object> getTestCaseData() {
+ Map<String, Object> data = new HashMap<>();
+ int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+ MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+ data.put("mtTarget", mtTarget);
+ // Arity after reducing because of long and double take 2 slots.
+ int realArity = mtTarget.parameterCount();
+ int filterArgsPos = Helper.RNG.nextInt(realArity + 1);
+ int filtersArgsArrayLength = Helper.RNG.nextInt(realArity + 1 - filterArgsPos);
+ MethodType mtFilter = TestMethods.randomMethodTypeGenerator(filtersArgsArrayLength);
+ data.put("mtFilter", mtFilter);
+ return data;
+ }
+
+ @Override
+ protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+ MethodType mtTarget = (MethodType) data.get("mtTarget");
+ MethodType mtFilter = (MethodType) data.get("mtFilter");
+ MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+ mtTarget.parameterList(), kind);
+ MethodHandle filter = TestMethods.filterGenerator(mtTarget.returnType(),
+ mtFilter.returnType(), kind);
+ return MethodHandles.filterReturnValue(target, filter);
+ }
+ },
+ INSERT_ARGUMENTS("insertArguments") {
+ @Override
+ public Map<String, Object> getTestCaseData() {
+ Map<String, Object> data = new HashMap<>();
+ int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+ MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+ data.put("mtTarget", mtTarget);
+ // Arity after reducing because of long and double take 2 slots.
+ int realArity = mtTarget.parameterCount();
+ int insertArgsPos = Helper.RNG.nextInt(realArity + 1);
+ data.put("insertArgsPos", insertArgsPos);
+ int insertArgsArrayLength = Helper.RNG.nextInt(realArity + 1 - insertArgsPos);
+ MethodType mtInsertArgs = MethodType.methodType(void.class, mtTarget.parameterList()
+ .subList(insertArgsPos, insertArgsPos + insertArgsArrayLength));
+ data.put("mtInsertArgs", mtInsertArgs);
+ return data;
+ }
+
+ @Override
+ protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+ MethodType mtTarget = (MethodType) data.get("mtTarget");
+ MethodType mtInsertArgs = (MethodType) data.get("mtInsertArgs");
+ int insertArgsPos = (int) data.get("insertArgsPos");
+ MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+ mtTarget.parameterList(), kind);
+ Object[] insertList = Helper.randomArgs(mtInsertArgs.parameterList());
+ return MethodHandles.insertArguments(target, insertArgsPos, insertList);
+ }
+ },
+ PERMUTE_ARGUMENTS("permuteArguments") {
+ @Override
+ public Map<String, Object> getTestCaseData() {
+ Map<String, Object> data = new HashMap<>();
+ int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY / 2);
+ MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+ // Arity after reducing because of long and double take 2 slots.
+ int realArity = mtTarget.parameterCount();
+ int[] permuteArgsReorderArray = new int[realArity];
+ int mtParmuteArgsNum = Helper.RNG.nextInt(Helper.MAX_ARITY);
+ mtParmuteArgsNum = mtParmuteArgsNum == 0 ? 1 : mtParmuteArgsNum;
+ MethodType mtPermuteArgs = TestMethods.randomMethodTypeGenerator(mtParmuteArgsNum);
+ mtTarget = mtTarget.changeReturnType(mtPermuteArgs.returnType());
+ for (int i = 0; i < realArity; i++) {
+ int mtPermuteArgsParNum = Helper.RNG.nextInt(mtPermuteArgs.parameterCount());
+ permuteArgsReorderArray[i] = mtPermuteArgsParNum;
+ mtTarget = mtTarget.changeParameterType(
+ i, mtPermuteArgs.parameterType(mtPermuteArgsParNum));
+ }
+ data.put("mtTarget", mtTarget);
+ data.put("permuteArgsReorderArray", permuteArgsReorderArray);
+ data.put("mtPermuteArgs", mtPermuteArgs);
+ return data;
+ }
+
+ @Override
+ protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+ MethodType mtTarget = (MethodType) data.get("mtTarget");
+ MethodType mtPermuteArgs = (MethodType) data.get("mtPermuteArgs");
+ int[] permuteArgsReorderArray = (int[]) data.get("permuteArgsReorderArray");
+ MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+ mtTarget.parameterList(), kind);
+ return MethodHandles.permuteArguments(target, mtPermuteArgs, permuteArgsReorderArray);
+ }
+ },
+ THROW_EXCEPTION("throwException") {
+ @Override
+ public Map<String, Object> getTestCaseData() {
+ Map<String, Object> data = new HashMap<>();
+ int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+ MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+ data.put("mtTarget", mtTarget);
+ return data;
+ }
+
+ @Override
+ protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
+ MethodType mtTarget = (MethodType) data.get("mtTarget");
+ Class<?> rType = mtTarget.returnType();
+ return MethodHandles.throwException(rType, Exception.class
+ );
+ }
+ },
+ GUARD_WITH_TEST("guardWithTest") {
+ @Override
+ public Map<String, Object> getTestCaseData() {
+ Map<String, Object> data = new HashMap<>();
+ int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+ MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+ data.put("mtTarget", mtTarget);
+ // Arity after reducing because of long and double take 2 slots.
+ int realArity = mtTarget.parameterCount();
+ int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1);
+ data.put("modifierMHArgNum", modifierMHArgNum);
+ return data;
+ }
+
+ @Override
+ protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+ MethodType mtTarget = (MethodType) data.get("mtTarget");
+ int modifierMHArgNum = (int) data.get("modifierMHArgNum");
+ TestMethods.Kind targetKind;
+ TestMethods.Kind fallbackKind;
+ if (kind.equals(TestMethods.Kind.ONE)) {
+ targetKind = TestMethods.Kind.ONE;
+ fallbackKind = TestMethods.Kind.TWO;
+ } else {
+ targetKind = TestMethods.Kind.TWO;
+ fallbackKind = TestMethods.Kind.ONE;
+ }
+ MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+ mtTarget.parameterList(), targetKind);
+ MethodHandle fallback = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+ mtTarget.parameterList(), fallbackKind);
+ MethodHandle test = TestMethods.methodHandleGenerator(boolean.class,
+ mtTarget.parameterList().subList(0, modifierMHArgNum), kind);
+ return MethodHandles.guardWithTest(test, target, fallback);
+ }
+ },
+ CATCH_EXCEPTION("catchException") {
+ @Override
+ public Map<String, Object> getTestCaseData() {
+ Map<String, Object> data = new HashMap<>();
+ int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+ MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+ data.put("mtTarget", mtTarget);
+ // Arity after reducing because of long and double take 2 slots.
+ int realArity = mtTarget.parameterCount();
+ int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1);
+ data.put("modifierMHArgNum", modifierMHArgNum);
+ return data;
+ }
+
+ @Override
+ protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+ MethodType mtTarget = (MethodType) data.get("mtTarget");
+ int modifierMHArgNum = (int) data.get("modifierMHArgNum");
+ MethodHandle target;
+ if (kind.equals(TestMethods.Kind.ONE)) {
+ target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+ mtTarget.parameterList(), TestMethods.Kind.ONE);
+ } else {
+ target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
+ mtTarget.parameterList(), TestMethods.Kind.EXCEPT);
+ }
+ List<Class<?>> handlerParamList = new ArrayList<>(mtTarget.parameterCount() + 1);
+ handlerParamList.add(Exception.class);
+ handlerParamList.addAll(mtTarget.parameterList().subList(0, modifierMHArgNum));
+ MethodHandle handler = TestMethods.methodHandleGenerator(
+ mtTarget.returnType(), handlerParamList, TestMethods.Kind.TWO);
+ return MethodHandles.catchException(target, Exception.class, handler);
+ }
+ },
+ INVOKER("invoker") {
+ @Override
+ public Map<String, Object> getTestCaseData() {
+ Map<String, Object> data = new HashMap<>();
+ int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+ MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+ data.put("mtTarget", mtTarget);
+ return data;
+ }
+
+ @Override
+ protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
+ MethodType mtTarget = (MethodType) data.get("mtTarget");
+ return MethodHandles.invoker(mtTarget);
+ }
+ },
+ EXACT_INVOKER("exactInvoker") {
+ @Override
+ public Map<String, Object> getTestCaseData() {
+ Map<String, Object> data = new HashMap<>();
+ int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+ MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+ data.put("mtTarget", mtTarget);
+ return data;
+ }
+
+ @Override
+ protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
+ MethodType mtTarget = (MethodType) data.get("mtTarget");
+ return MethodHandles.exactInvoker(mtTarget);
+ }
+ },
+ SPREAD_INVOKER("spreadInvoker") {
+ @Override
+ public Map<String, Object> getTestCaseData() {
+ Map<String, Object> data = new HashMap<>();
+ int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+ MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+ data.put("mtTarget", mtTarget);
+ // Arity after reducing because of long and double take 2 slots.
+ int realArity = mtTarget.parameterCount();
+ int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1);
+ data.put("modifierMHArgNum", modifierMHArgNum);
+ return data;
+ }
+
+ @Override
+ protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
+ MethodType mtTarget = (MethodType) data.get("mtTarget");
+ int modifierMHArgNum = (int) data.get("modifierMHArgNum");
+ return MethodHandles.spreadInvoker(mtTarget, modifierMHArgNum);
+ }
+ },
+ ARRAY_ELEMENT_GETTER("arrayElementGetter") {
+ @Override
+ public Map<String, Object> getTestCaseData() {
+ Map<String, Object> data = new HashMap<>();
+ int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+ MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+ data.put("mtTarget", mtTarget);
+ return data;
+ }
+
+ @Override
+ protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
+ MethodType mtTarget = (MethodType) data.get("mtTarget");
+ Class<?> rType = mtTarget.returnType();
+ if (rType == void.class) {
+ rType = Object.class;
+ }
+ return MethodHandles.arrayElementGetter(Array.newInstance(rType, 2).getClass());
+ }
+ },
+ ARRAY_ELEMENT_SETTER("arrayElementSetter") {
+ @Override
+ public Map<String, Object> getTestCaseData() {
+ Map<String, Object> data = new HashMap<>();
+ int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+ MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+ data.put("mtTarget", mtTarget);
+ return data;
+ }
+
+ @Override
+ protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
+ MethodType mtTarget = (MethodType) data.get("mtTarget");
+ Class<?> rType = mtTarget.returnType();
+ if (rType == void.class) {
+ rType = Object.class;
+ }
+ return MethodHandles.arrayElementSetter(Array.newInstance(rType, 2).getClass());
+ }
+ },
+ CONSTANT("constant") {
+ @Override
+ public Map<String, Object> getTestCaseData() {
+ Map<String, Object> data = new HashMap<>();
+ int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+ MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+ data.put("mtTarget", mtTarget);
+ return data;
+ }
+
+ @Override
+ protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
+ MethodType mtTarget = (MethodType) data.get("mtTarget");
+ Class<?> rType = mtTarget.returnType();
+ if (rType == void.class) {
+ rType = Object.class;
+ }
+ if (rType.equals(boolean.class)) {
+ // There should be the same return values because for default values there are special "zero" forms
+ return MethodHandles.constant(rType, true);
+ } else {
+ return MethodHandles.constant(rType, kind.getValue(rType));
+ }
+ }
+ },
+ IDENTITY("identity") {
+ @Override
+ public Map<String, Object> getTestCaseData() {
+ Map<String, Object> data = new HashMap<>();
+ int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
+ MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
+ data.put("mtTarget", mtTarget);
+ return data;
+ }
+
+ @Override
+ protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
+ MethodType mtTarget = (MethodType) data.get("mtTarget");
+ Class<?> rType = mtTarget.returnType();
+ if (rType == void.class) {
+ rType = Object.class;
+ }
+ return MethodHandles.identity(rType);
+ }
+ };
+
+ /**
+ * Test method's name.
+ */
+ public final String name;
+
+ private TestMethods(String name) {
+ this.name = name;
+ }
+
+ protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+ throw new UnsupportedOperationException("TESTBUG: getMH method is not implemented for test method " + this);
+ }
+
+ /**
+ * Creates an adapter method handle depending on a test method from
+ * MethodHandles class. Adapter is what is returned by the test method. This
+ * method is able to create two kinds of adapters, their type will be the
+ * same, but return values are different.
+ *
+ * @param data a Map containing data to create a method handle, can be
+ * obtained by {@link #getTestCaseData} method
+ * @param kind defines whether adapter ONE or adapter TWO will be
+ * initialized. Should be equal to TestMethods.Kind.ONE or
+ * TestMethods.Kind.TWO
+ * @return Method handle adapter that behaves according to
+ * TestMethods.Kind.ONE or TestMethods.Kind.TWO
+ * @throws java.lang.NoSuchMethodException
+ * @throws java.lang.IllegalAccessException
+ */
+ public MethodHandle getTestCaseMH(Map<String, Object> data, TestMethods.Kind kind)
+ throws NoSuchMethodException, IllegalAccessException {
+ if (data == null) {
+ throw new Error(String.format("TESTBUG: Data for test method %s is not prepared",
+ this.name));
+ }
+ if (!kind.equals(TestMethods.Kind.ONE) && !kind.equals(TestMethods.Kind.TWO)) {
+ throw new IllegalArgumentException("TESTBUG: Wrong \"kind\" (" + kind
+ + ") arg to getTestCaseMH function."
+ + " Should be Kind.ONE or Kind.TWO");
+ }
+ return getMH(data, kind);
+ }
+
+ /**
+ * Returns a data Map needed for {@link #getTestCaseMH} method.
+ *
+ * @return data Map needed for {@link #getTestCaseMH} method
+ */
+ public Map<String, Object> getTestCaseData() {
+ throw new UnsupportedOperationException(
+ "TESTBUG: getTestCaseData method is not implemented for test method " + this);
+ }
+
+ /**
+ * Enumeration used in methodHandleGenerator to define whether a MH returned
+ * by this method returns "2" in different type representations, "4", or
+ * throw an Exception.
+ */
+ public static enum Kind {
+
+ ONE(2),
+ TWO(4),
+ EXCEPT(0);
+
+ private final int value;
+
+ private Object getValue(Class<?> cl) {
+ return Helper.castToWrapper(value, cl);
+ }
+
+ private MethodHandle getBasicMH(Class<?> rType) throws NoSuchMethodException, IllegalAccessException {
+ MethodHandle result = null;
+ switch (this) {
+ case ONE:
+ case TWO:
+ if (rType.equals(void.class)) {
+ result = MethodHandles.lookup().findVirtual(Kind.class, "returnVoid", MethodType.methodType(void.class));
+ result = MethodHandles.insertArguments(result, 0, this);
+ } else {
+ result = MethodHandles.constant(rType, getValue(rType));
+ }
+ break;
+ case EXCEPT:
+ result = MethodHandles.throwException(rType, Exception.class);
+ result = MethodHandles.insertArguments(result, 0, new Exception());
+ break;
+ }
+ return result;
+ }
+
+ private void returnVoid() {
+ }
+
+ private Kind(int value) {
+ this.value = value;
+ }
+ }
+
+ /**
+ * Routine used to obtain a randomly generated method type.
+ *
+ * @param arity Arity of returned method type.
+ * @return MethodType generated randomly.
+ */
+ private static MethodType randomMethodTypeGenerator(int arity) {
+ final Class<?>[] CLASSES = {
+ Object.class,
+ int.class,
+ boolean.class,
+ byte.class,
+ short.class,
+ char.class,
+ long.class,
+ float.class,
+ double.class
+ };
+ if (arity > Helper.MAX_ARITY) {
+ throw new IllegalArgumentException(
+ String.format("Arity should not exceed %d!", Helper.MAX_ARITY));
+ }
+ List<Class<?>> list = Helper.randomClasses(CLASSES, arity);
+ list = Helper.getParams(list, false, arity);
+ int i = Helper.RNG.nextInt(CLASSES.length + 1);
+ Class<?> rtype = i == CLASSES.length ? void.class : CLASSES[i];
+ return MethodType.methodType(rtype, list);
+ }
+
+ /**
+ * Routine used to obtain a method handles of a given type an kind (return
+ * value).
+ *
+ * @param returnType Type of MH return value.
+ * @param argTypes Types of MH args.
+ * @param kind Defines whether the obtained MH returns "1" or "2".
+ * @return Method handle of the given type.
+ * @throws NoSuchMethodException
+ * @throws IllegalAccessException
+ */
+ private static MethodHandle methodHandleGenerator(Class<?> returnType,
+ List<Class<?>> argTypes, TestMethods.Kind kind)
+ throws NoSuchMethodException, IllegalAccessException {
+ MethodHandle result;
+ result = kind.getBasicMH(returnType);
+ return Helper.addTrailingArgs(result, argTypes.size(), argTypes);
+ }
+
+ /**
+ * Routine that generates filter method handles to test
+ * MethodHandles.filterArguments method.
+ *
+ * @param inputType Filter's argument type.
+ * @param returnType Filter's return type.
+ * @param kind Filter's return value definer.
+ * @return A filter method handle, that takes one argument.
+ * @throws NoSuchMethodException
+ * @throws IllegalAccessException
+ */
+ private static MethodHandle filterGenerator(Class<?> inputType, Class<?> returnType,
+ TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
+ MethodHandle tmpMH = kind.getBasicMH(returnType);
+ if (inputType.equals(void.class)) {
+ return tmpMH;
+ }
+ ArrayList<Class<?>> inputTypeList = new ArrayList<>(1);
+ inputTypeList.add(inputType);
+ return Helper.addTrailingArgs(tmpMH, 1, inputTypeList);
+ }
+
+ private static int argSlotsCount(MethodType mt) {
+ int result = 0;
+ for (Class cl : mt.parameterArray()) {
+ if (cl.equals(long.class) || cl.equals(double.class)) {
+ result += 2;
+ } else {
+ result++;
+ }
+ }
+ return result;
+ }
+
+ private static List<Class<?>> reduceArgListToSlotsCount(List<Class<?>> list,
+ int desiredSlotCount) {
+ List<Class<?>> result = new ArrayList<>(desiredSlotCount);
+ int count = 0;
+ for (Class<?> cl : list) {
+ if (count >= desiredSlotCount) {
+ break;
+ }
+ if (cl.equals(long.class) || cl.equals(double.class)) {
+ count += 2;
+ } else {
+ count++;
+ }
+ result.add(cl);
+ }
+ return result;
+ }
+}
--- a/jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java Wed Jul 05 20:01:44 2017 +0200
@@ -42,6 +42,7 @@
public class CatchExceptionTest {
private static final List<Class<?>> ARGS_CLASSES;
protected static final int MAX_ARITY = Helper.MAX_ARITY - 1;
+
static {
Class<?> classes[] = {
Object.class,
@@ -52,11 +53,8 @@
double[].class,
String.class,
};
- List<Class<?>> list = new ArrayList<>(MAX_ARITY);
- for (int i = 0; i < MAX_ARITY; ++i) {
- list.add(classes[Helper.RNG.nextInt(classes.length)]);
- }
- ARGS_CLASSES = Collections.unmodifiableList(list);
+ ARGS_CLASSES = Collections.unmodifiableList(
+ Helper.randomClasses(classes, MAX_ARITY));
}
private final TestCase testCase;
@@ -66,7 +64,6 @@
private int dropped;
private MethodHandle thrower;
-
public CatchExceptionTest(TestCase testCase, final boolean isVararg, final int argsCount,
final int catchDrops) {
this.testCase = testCase;
@@ -107,37 +104,7 @@
}
private List<Class<?>> getThrowerParams(boolean isVararg, int argsCount) {
- boolean unmodifiable = true;
- List<Class<?>> classes;
- classes = ARGS_CLASSES.subList(0,
- Math.min(argsCount, (MAX_ARITY / 2) - 1));
- int extra = 0;
- if (argsCount >= MAX_ARITY / 2) {
- classes = new ArrayList<>(classes);
- unmodifiable = false;
- extra = (int) classes.stream().filter(Helper::isDoubleCost).count();
- int i = classes.size();
- while (classes.size() + extra < argsCount) {
- Class<?> aClass = ARGS_CLASSES.get(i);
- if (Helper.isDoubleCost(aClass)) {
- ++extra;
- if (classes.size() + extra >= argsCount) {
- break;
- }
- }
- classes.add(aClass);
- }
- }
- if (isVararg && classes.size() > 0) {
- if (unmodifiable) {
- classes = new ArrayList<>(classes);
- }
- int last = classes.size() - 1;
- Class<?> aClass = classes.get(classes.size() - 1);
- aClass = Array.newInstance(aClass, 2).getClass();
- classes.set(last, aClass);
- }
- return classes;
+ return Helper.getParams(ARGS_CLASSES, isVararg, argsCount);
}
--- a/jdk/test/java/lang/invoke/lambda/LUtils.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/java/lang/invoke/lambda/LUtils.java Wed Jul 05 20:01:44 2017 +0200
@@ -37,8 +37,6 @@
* support infrastructure to invoke a java class from the command line
*/
class LUtils {
- static final sun.tools.jar.Main jarTool =
- new sun.tools.jar.Main(System.out, System.err, "jar-tool");
static final com.sun.tools.javac.Main javac =
new com.sun.tools.javac.Main();
static final File cwd = new File(".").getAbsoluteFile();
@@ -49,6 +47,10 @@
static final File JAVA_BIN_FILE = new File(JAVAHOME, "bin");
static final File JAVA_CMD = new File(JAVA_BIN_FILE,
isWindows ? "java.exe" : "java");
+ static final File JAR_BIN_FILE =
+ new File(new File(JAVAHOME).getParentFile(), "bin");
+ static final File JAR_CMD = new File(JAR_BIN_FILE,
+ isWindows ? "jar.exe" : "jar");
protected LUtils() {
}
--- a/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java Wed Jul 05 20:01:44 2017 +0200
@@ -67,12 +67,17 @@
compile(javacArgs);
File jarFile = new File("foo.jar");
String[] jargs = {"cvf", jarFile.getName(), doprivClass.getName()};
- jarTool.run(jargs);
+ TestResult tr = doExec(JAR_CMD.getAbsolutePath(),
+ "cvf", jarFile.getName(),
+ doprivClass.getName());
+ if (tr.exitValue != 0){
+ throw new RuntimeException(tr.toString());
+ }
doprivJava.delete();
doprivClass.delete();
- TestResult tr = doExec(JAVA_CMD.getAbsolutePath(),
- "-Xbootclasspath/p:foo.jar",
- "-cp", ".", "Bar");
+ tr = doExec(JAVA_CMD.getAbsolutePath(),
+ "-Xbootclasspath/p:foo.jar",
+ "-cp", ".", "Bar");
tr.assertZero("testDoPrivileged fails");
barJava.delete();
barClass.delete();
--- a/jdk/test/java/math/BigDecimal/ZeroScalingTests.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/java/math/BigDecimal/ZeroScalingTests.java Wed Jul 05 20:01:44 2017 +0200
@@ -23,8 +23,10 @@
/*
* @test
- * @bug 4902952 4905407 4916149
- * @summary Tests that the scale of zero is propagated properly and has the proper effect.
+ * @bug 4902952 4905407 4916149 8057793
+ * @summary Tests that the scale of zero is propagated properly and has the
+ * proper effect and that setting the scale to zero does not mutate the
+ * BigDecimal.
* @author Joseph D. Darcy
*/
@@ -445,6 +447,16 @@
return failures;
}
+ static int setScaleDoesNotMutateTest() {
+ BigDecimal total = new BigDecimal("258815507198903607775511093103396443816569106750031264155319238473795838680758514810110764742309284477206138527975952150289602995045050194333030191178778772026538699925775139201970526695485362661420908248887297829319881475178467494779683293036572059595504702727301324759997409522995072582369210284334718757260859794972695026582432867589093687280300148141501712013226636373167978223780290547640482160818746599330924736802844173226042389174403401903999447463440670236056324929325189403433689"
+ + ".426167432065785331444814035799717606745777287606858873045971898862329763544687891847664736523584843544347118836628373041412918374550458884706686730726101338872517021688769782894793734049819222924171842793485919753186993388451909096042127903835765393729547730953942175461146061715108701615615142134282261293656760570061554783195726716403304101469782303957325142638493327692352838806741611887655695029948975509680496573999174402058593454203190963443179532640446352828089016874853634851387762579319853267317320515941105912189838719919259277721994880193541634872882180184303434360412344059435559680494807415573269199203376126242271766939666939316648575065702750502798973418978204972336924254702551350654650573582614211506856383897692911422458286912085339575875324832979140870119455620532272318122103640233069115700020760625493816902806241630788230268031695140687964931377988962507263990468276009750998066442971308866347136022907166625330623130307555914930120150437900510530537258665172619821272937026713977709974434967165159545592482710663639966781678268622620229577009317698254134914742098420792313931843709810905414336383757407675429663714210967924767434203021205270369316797752411974617662200898086335322218191674846795163102021505555508444216708745911194321674887527227200297039471799580744303346354057273540730643842091810899490590914195225087593013834388801018488174855060306804024894292757613618190472234110859436472645203753139820658279559340251226992556744343475086923568365637919479462424794554522865559888240039662899509652221329892034706445253487898044421278283079233226845124525434586324657471286953226255430662125870993375281512713207125720748163498642795960457639954616530163959004770092547297392499137383176609646505351001304840762905826237024982330597805063521162285806541220110524989649256399233792799406995068469271941269511818994954109392839548141262324660472253632382325038836831429045617036015122388070240133760858500132713255407855625837956886349324981003917084922808187223285051144454915441134217743066575863563572152133978905444998209075763950909784148142018992367290485890072303179512881131769414783097454103103347826517701720263541869335631166977965013552647906729408522950996105479525445916501155305220090853891226367184989434453290788068397817927893708837722255115237672194162924260945492012622891770365546831236789867922136747819364833843397165107825773447549885351449899330007200651144003961228091210630807333236718793283427788965479074476288255387824982443633190938302785760754436525586544523339170400053128503337395428393881357669568532722167493096151221381017320147344991331421789379785964440840684363041795410525097564979585773948558651896834067324427900848255265001498890329859444233861478388742393060996236783742654761350763876989363052609107226398858310051497856931093693697981165801539060516895227818925342535261227134364063673285588256280386915163875872231395348293505967057794409379709079685798908660258077792158532257603211711587587586356431658240229896344639704");
+ if (total.setScale(0, RoundingMode.DOWN).equals(total.setScale(0, RoundingMode.DOWN))) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+
public static void main(String argv[]) {
int failures = 0;
@@ -455,6 +467,7 @@
failures += setScaleTests();
failures += toEngineeringStringTests();
failures += ulpTests();
+ failures += setScaleDoesNotMutateTest();
if (failures > 0 ) {
throw new RuntimeException("Incurred " + failures + " failures" +
--- a/jdk/test/java/math/BigInteger/BigIntegerTest.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/java/math/BigInteger/BigIntegerTest.java Wed Jul 05 20:01:44 2017 +0200
@@ -71,6 +71,7 @@
static final int BITS_TOOM_COOK_SQUARE = 6912;
static final int BITS_SCHOENHAGE_BASE = 640;
static final int BITS_BURNIKEL_ZIEGLER = 2560;
+ static final int BITS_BURNIKEL_ZIEGLER_OFFSET = 1280;
static final int ORDER_SMALL = 60;
static final int ORDER_MEDIUM = 100;
@@ -288,19 +289,19 @@
* where {@code abs(u) > abs(v)} and {@code a > b && b > 0}, then if
* {@code w/z = q1*z + r1} and {@code u/v = q2*v + r2}, then
* {@code q1 = q2*pow(2,a-b)} and {@code r1 = r2*pow(2,b)}. The test
- * ensures that {@code v} is just under the B-Z threshold and that {@code w}
- * and {@code z} are both over the threshold. This implies that {@code u/v}
- * uses the standard division algorithm and {@code w/z} uses the B-Z
- * algorithm. The results of the two algorithms are then compared using the
- * observation described in the foregoing and if they are not equal a
- * failure is logged.
+ * ensures that {@code v} is just under the B-Z threshold, that {@code z} is
+ * over the threshold and {@code w} is much larger than {@code z}. This
+ * implies that {@code u/v} uses the standard division algorithm and
+ * {@code w/z} uses the B-Z algorithm. The results of the two algorithms
+ * are then compared using the observation described in the foregoing and
+ * if they are not equal a failure is logged.
*/
public static void divideLarge() {
int failCount = 0;
- BigInteger base = BigInteger.ONE.shiftLeft(BITS_BURNIKEL_ZIEGLER - 33);
+ BigInteger base = BigInteger.ONE.shiftLeft(BITS_BURNIKEL_ZIEGLER + BITS_BURNIKEL_ZIEGLER_OFFSET - 33);
for (int i=0; i<SIZE; i++) {
- BigInteger addend = new BigInteger(BITS_BURNIKEL_ZIEGLER - 34, rnd);
+ BigInteger addend = new BigInteger(BITS_BURNIKEL_ZIEGLER + BITS_BURNIKEL_ZIEGLER_OFFSET - 34, rnd);
BigInteger v = base.add(addend);
BigInteger u = v.multiply(BigInteger.valueOf(2 + rnd.nextInt(Short.MAX_VALUE - 1)));
@@ -312,14 +313,14 @@
v = v.negate();
}
- int a = 17 + rnd.nextInt(16);
+ int a = BITS_BURNIKEL_ZIEGLER_OFFSET + rnd.nextInt(16);
int b = 1 + rnd.nextInt(16);
- BigInteger w = u.multiply(BigInteger.valueOf(1L << a));
- BigInteger z = v.multiply(BigInteger.valueOf(1L << b));
+ BigInteger w = u.multiply(BigInteger.ONE.shiftLeft(a));
+ BigInteger z = v.multiply(BigInteger.ONE.shiftLeft(b));
BigInteger[] divideResult = u.divideAndRemainder(v);
- divideResult[0] = divideResult[0].multiply(BigInteger.valueOf(1L << (a - b)));
- divideResult[1] = divideResult[1].multiply(BigInteger.valueOf(1L << b));
+ divideResult[0] = divideResult[0].multiply(BigInteger.ONE.shiftLeft(a - b));
+ divideResult[1] = divideResult[1].multiply(BigInteger.ONE.shiftLeft(b));
BigInteger[] bzResult = w.divideAndRemainder(z);
if (divideResult[0].compareTo(bzResult[0]) != 0 ||
--- a/jdk/test/java/net/NetworkInterface/Test.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/java/net/NetworkInterface/Test.java Wed Jul 05 20:01:44 2017 +0200
@@ -22,7 +22,9 @@
*/
/* @test
- * @bug 4405354 6594296
+ * @bug 4405354 6594296 8058216
+ * @run main Test
+ * @run main/othervm -Djava.net.preferIPv4Stack=true Test
* @summary Basic tests for NetworkInterface
*/
import java.net.NetworkInterface;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/channels/FileChannel/BlockDeviceSize.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2014, 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 8054029
+ * @summary Block devices should not report size=0 on Linux
+ */
+
+import java.io.RandomAccessFile;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.channels.FileChannel;
+import java.nio.file.AccessDeniedException;
+import java.nio.file.NoSuchFileException;
+import static java.nio.file.StandardOpenOption.*;
+
+
+public class BlockDeviceSize {
+ private static final String BLK_FNAME = "/dev/sda1";
+ private static final Path BLK_PATH = Paths.get(BLK_FNAME);
+
+ public static void main(String[] args) throws Throwable {
+ try (FileChannel ch = FileChannel.open(BLK_PATH, READ);
+ RandomAccessFile file = new RandomAccessFile(BLK_FNAME, "r")) {
+
+ long size1 = ch.size();
+ long size2 = file.length();
+ if (size1 != size2) {
+ throw new RuntimeException("size differs when retrieved" +
+ " in different ways: " + size1 + " != " + size2);
+ }
+ System.out.println("OK");
+
+ } catch (NoSuchFileException nsfe) {
+ System.err.println("File " + BLK_FNAME + " not found." +
+ " Skipping test");
+ } catch (AccessDeniedException ade) {
+ System.err.println("Access to " + BLK_FNAME + " is denied." +
+ " Run test as root.");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/AccessController/LimitedDoPrivilegedWithNullPerms.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2013,2014, 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 8050281
+ * @summary Test that NullPointerException is thrown if any element of perms
+ * parameter is null
+ * @run testng LimitedDoPrivilegedWithNullPerms
+ */
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Permission;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.PropertyPermission;
+import org.testng.annotations.Test;
+
+public class LimitedDoPrivilegedWithNullPerms {
+
+ AccessControlContext acc = AccessController.getContext();
+ Permission p1 = new PropertyPermission("user.name", "read");
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void test1() {
+ AccessController.doPrivileged(
+ (PrivilegedAction<Void>) () -> null, acc, null);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void test2() {
+ AccessController.doPrivileged(
+ (PrivilegedAction<Void>) () -> null, acc, p1, null);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void test3() {
+ AccessController.doPrivilegedWithCombiner(
+ (PrivilegedAction<Void>) () -> null, acc, null);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void test4() {
+ AccessController.doPrivilegedWithCombiner(
+ (PrivilegedAction<Void>) () -> null, acc, p1, null);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void test5() throws PrivilegedActionException {
+ AccessController.doPrivileged(
+ (PrivilegedExceptionAction<Void>) () -> null,
+ acc, null);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void test6() throws PrivilegedActionException {
+ AccessController.doPrivileged(
+ (PrivilegedExceptionAction<Void>) () -> null,
+ acc, p1, null);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void test7() throws PrivilegedActionException {
+ AccessController.doPrivilegedWithCombiner(
+ (PrivilegedExceptionAction<Void>) () -> null,
+ acc, null);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void test8() throws PrivilegedActionException {
+ AccessController.doPrivilegedWithCombiner(
+ (PrivilegedExceptionAction<Void>) () -> null,
+ acc, p1, null);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/AccessController/LimitedDoPrivilegedWithThread.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2013,2014, 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 8050281
+ * @summary Test limited doprivileged action with trhead calls.
+ * @run main/othervm/policy=policy LimitedDoPrivilegedWithThread
+ */
+import java.io.FilePermission;
+import java.security.AccessControlContext;
+import java.security.AccessControlException;
+import java.security.AccessController;
+import java.security.Permission;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.PropertyPermission;
+
+public class LimitedDoPrivilegedWithThread {
+
+ private static final Permission PROPERTYPERM
+ = new PropertyPermission("user.name", "read");
+ private static final Permission FILEPERM
+ = new FilePermission("*", "read");
+ private static final AccessControlContext ACC
+ = new AccessControlContext(
+ new ProtectionDomain[]{new ProtectionDomain(null, null)});
+
+ public static void main(String args[]) {
+ //parent thread without any permission
+ AccessController.doPrivileged(
+ (PrivilegedAction) () -> {
+ Thread ct = new Thread(
+ new ChildThread(PROPERTYPERM, FILEPERM));
+ ct.start();
+ try {
+ ct.join();
+ } catch (InterruptedException ie) {
+ Thread.currentThread().interrupt();
+ ie.printStackTrace();
+ throw new RuntimeException("Unexpected InterruptedException");
+ }
+ return null;
+ }, ACC);
+ }
+}
+
+class ChildThread implements Runnable {
+
+ private final Permission P1;
+ private final Permission P2;
+ private boolean catchACE = false;
+
+ public ChildThread(Permission p1, Permission p2) {
+ this.P1 = p1;
+ this.P2 = p2;
+ }
+
+ @Override
+ public void run() {
+ //Verified that child thread has permission p1,
+ runTest(null, P1, false, 1);
+ //Verified that child thread inherits parent thread's access control context
+ AccessControlContext childAcc = AccessController.getContext();
+ runTest(childAcc, P1, true, 2);
+ //Verified that we can give permision p2 to limit the "privilege" of the
+ //class calling doprivileged action, stack walk will continue
+ runTest(null, P2, true, 3);
+
+ }
+
+ public void runTest(AccessControlContext acc, Permission perm,
+ boolean expectACE, int id) {
+
+ AccessController.doPrivileged(
+ (PrivilegedAction) () -> {
+ try {
+ AccessController.getContext().checkPermission(P1);
+ } catch (AccessControlException ace) {
+ catchACE = true;
+ }
+ if (catchACE ^ expectACE) {
+ throw new RuntimeException("test" + id + " failed");
+ }
+ return null;
+ }, acc, perm);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/AccessController/policy Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,4 @@
+grant{
+ permission java.util.PropertyPermission "user.name", "read";
+ permission java.io.FilePermission "*", "read";
+};
--- a/jdk/test/java/sql/test/sql/TimestampTests.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/java/sql/test/sql/TimestampTests.java Wed Jul 05 20:01:44 2017 +0200
@@ -27,14 +27,40 @@
import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDateTime;
+import java.time.ZoneId;
import java.util.Calendar;
+import java.util.TimeZone;
import static org.testng.Assert.*;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import util.BaseTest;
public class TimestampTests extends BaseTest {
+ private static TimeZone defaultTimeZone = null;
+
+ /*
+ * Need to set and use a custom TimeZone which does not
+ * observe daylight savings time for this test.
+ */
+ @BeforeClass
+ public static void setUpClass() throws Exception {
+ defaultTimeZone = TimeZone.getDefault();
+ TimeZone tzone = TimeZone.getTimeZone("GMT+01");
+ assertFalse(tzone.observesDaylightTime());
+ TimeZone.setDefault(tzone);
+ }
+
+ /*
+ * Conservatively reset the default time zone after test.
+ */
+ @AfterClass
+ public static void tearDownClass() throws Exception {
+ TimeZone.setDefault(defaultTimeZone);
+ }
+
/*
* Validate an IllegalArgumentException is thrown for an invalid Timestamp
*/
@@ -610,6 +636,12 @@
"Error with Nanos");
}
+ @Test(dataProvider = "validTimestampLongValues")
+ public void test52(long value, String ts) {
+ Timestamp ts1 = new Timestamp(value);
+ assertEquals(ts1.toString(), ts, "ts1.toString() != ts");
+ }
+
/*
* DataProvider used to provide Timestamps which are not valid and are used
* to validate that an IllegalArgumentException will be thrown from the
@@ -678,6 +710,40 @@
};
}
+ @DataProvider(name = "validTimestampLongValues")
+ private Object[][] validTimestampLongValues() {
+ return new Object[][]{
+ {1L, "1970-01-01 01:00:00.001"},
+ {-3600*1000L - 1, "1969-12-31 23:59:59.999"},
+ {-(20000L*365*24*60*60*1000), "18018-08-28 01:00:00.0"},
+ {Timestamp.valueOf("1961-08-30 11:22:33").getTime(), "1961-08-30 11:22:33.0"},
+ {Timestamp.valueOf("1961-08-30 11:22:33.54321000").getTime(), "1961-08-30 11:22:33.543"}, // nanoprecision lost
+ {new Timestamp(114, 10, 10, 10, 10, 10, 100000000).getTime(), "2014-11-10 10:10:10.1"},
+ {new Timestamp(0, 10, 10, 10, 10, 10, 100000).getTime(), "1900-11-10 10:10:10.0"}, // nanoprecision lost
+ {new Date(114, 10, 10).getTime(), "2014-11-10 00:00:00.0"},
+ {new Date(0, 10, 10).getTime(), "1900-11-10 00:00:00.0"},
+ {LocalDateTime.of(1960, 10, 10, 10, 10, 10, 50000).atZone(ZoneId.of("America/Los_Angeles"))
+ .toInstant().toEpochMilli(), "1960-10-10 19:10:10.0"},
+
+ // millisecond timestamps wraps around at year 1, so Long.MIN_VALUE looks similar
+ // Long.MAX_VALUE, while actually representing 292278994 BCE
+ {Long.MIN_VALUE, "292278994-08-17 08:12:55.192"},
+ {Long.MAX_VALUE + 1, "292278994-08-17 08:12:55.192"},
+ {Long.MAX_VALUE, "292278994-08-17 08:12:55.807"},
+ {Long.MIN_VALUE - 1, "292278994-08-17 08:12:55.807"},
+
+ // wrap around point near 0001-01-01, test that we never get a negative year:
+ {-(1970L*365*24*60*60*1000), "0001-04-25 01:00:00.0"},
+ {-(1970L*365*24*60*60*1000 + 115*24*60*60*1000L), "0001-12-31 01:00:00.0"},
+ {-(1970L*365*24*60*60*1000 + 115*24*60*60*1000L - 23*60*60*1000L), "0001-01-01 00:00:00.0"},
+
+ {LocalDateTime.of(0, 1, 1, 10, 10, 10, 50000).atZone(ZoneId.of("America/Los_Angeles"))
+ .toInstant().toEpochMilli() - 2*24*60*60*1000L, "0001-01-01 19:03:08.0"}, // 1 BCE
+ {LocalDateTime.of(0, 1, 1, 10, 10, 10, 50000).atZone(ZoneId.of("America/Los_Angeles"))
+ .toInstant().toEpochMilli() - 3*24*60*60*1000L, "0002-12-31 19:03:08.0"} // 2 BCE
+ };
+ }
+
/*
* DataProvider used to provide Timestamp and Nanos values in order to
* validate that the correct Nanos value is generated from the specified
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/zip/DataDescriptorSignatureMissing.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2012 Google, Inc. 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 8056934
+ * @summary Check ability to read zip files created by python zipfile
+ * implementation, which fails to write optional (but recommended) data
+ * descriptor signatures. Repro scenario is a Java -> Python -> Java round trip:
+ * - ZipOutputStream creates zip file with DEFLATED entries and data
+ * descriptors with optional signature "PK0x0708".
+ * - Python reads those entries, preserving the 0x08 flag byte
+ * - Python outputs those entries with data descriptors lacking the
+ * optional signature.
+ * - ZipInputStream cannot handle the missing signature
+ *
+ * No way to adapt the technique in this test to get a ZIP64 zip file
+ * without data descriptors was found.
+ *
+ * @ignore This test has brittle dependencies on an external working python.
+ */
+
+import java.io.*;
+import java.util.zip.*;
+
+public class DataDescriptorSignatureMissing {
+ void printStream(InputStream is) throws IOException {
+ Reader r = new InputStreamReader(is);
+ StringBuilder sb = new StringBuilder();
+ char[] buf = new char[1024];
+ int n;
+ while ((n = r.read(buf)) > 0) {
+ sb.append(buf, 0, n);
+ }
+ System.out.print(sb);
+ }
+
+ int entryCount(File zipFile) throws IOException {
+ try (FileInputStream fis = new FileInputStream(zipFile);
+ ZipInputStream zis = new ZipInputStream(fis)) {
+ for (int count = 0;; count++)
+ if (zis.getNextEntry() == null)
+ return count;
+ }
+ }
+
+ void test(String[] args) throws Throwable {
+ if (! new File("/usr/bin/python").canExecute())
+ return;
+
+ // Create a java zip file with DEFLATED entries and data
+ // descriptors with signatures.
+ final File in = new File("in.zip");
+ final File out = new File("out.zip");
+ final int count = 3;
+ try (FileOutputStream fos = new FileOutputStream(in);
+ ZipOutputStream zos = new ZipOutputStream(fos)) {
+ for (int i = 0; i < count; i++) {
+ ZipEntry ze = new ZipEntry("hello.python" + i);
+ ze.setMethod(ZipEntry.DEFLATED);
+ zos.putNextEntry(ze);
+ zos.write(new byte[10]);
+ zos.closeEntry();
+ }
+ }
+
+ // Copy the zip file using python's zipfile module
+ String[] python_program_lines = {
+ "import os",
+ "import zipfile",
+ "input_zip = zipfile.ZipFile('in.zip', mode='r')",
+ "output_zip = zipfile.ZipFile('out.zip', mode='w')",
+ "count08 = 0",
+ "for input_info in input_zip.infolist():",
+ " output_info = input_info",
+ " if output_info.flag_bits & 0x08 == 0x08:",
+ " count08 += 1",
+ " output_zip.writestr(output_info, input_zip.read(input_info))",
+ "output_zip.close()",
+ "if count08 == 0:",
+ " raise ValueError('Expected to see entries with 0x08 flag_bits set')",
+ };
+ StringBuilder python_program_builder = new StringBuilder();
+ for (String line : python_program_lines)
+ python_program_builder.append(line).append('\n');
+ String python_program = python_program_builder.toString();
+ String[] cmdline = { "/usr/bin/python", "-c", python_program };
+ ProcessBuilder pb = new ProcessBuilder(cmdline);
+ pb.redirectErrorStream(true);
+ Process p = pb.start();
+ printStream(p.getInputStream());
+ p.waitFor();
+ equal(p.exitValue(), 0);
+
+ File pythonZipFile = new File("out.zip");
+ check(pythonZipFile.exists());
+
+ equal(entryCount(in),
+ entryCount(out));
+
+ // We expect out to be identical to in, except for the removal of
+ // the optional data descriptor signatures.
+ final int SIG_LENGTH = 4; // length of a zip signature - PKxx
+ equal(in.length(),
+ out.length() + SIG_LENGTH * count);
+
+ in.delete();
+ out.delete();
+ }
+
+ //--------------------- Infrastructure ---------------------------
+ volatile int passed = 0, failed = 0;
+ void pass() {passed++;}
+ void fail() {failed++; Thread.dumpStack();}
+ void fail(String msg) {System.err.println(msg); fail();}
+ void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ void check(boolean cond) {if (cond) pass(); else fail();}
+ void equal(Object x, Object y) {
+ if (x == null ? y == null : x.equals(y)) pass();
+ else fail(x + " not equal to " + y);}
+ public static void main(String[] args) throws Throwable {
+ new DataDescriptorSignatureMissing().instanceMain(args);}
+ public void instanceMain(String[] args) throws Throwable {
+ try {test(args);} catch (Throwable t) {unexpected(t);}
+ System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- a/jdk/test/javax/management/monitor/AttributeArbitraryDataTypeTest.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/javax/management/monitor/AttributeArbitraryDataTypeTest.java Wed Jul 05 20:01:44 2017 +0200
@@ -58,9 +58,9 @@
public class AttributeArbitraryDataTypeTest implements NotificationListener {
// Flag to notify that a message has been received
- private boolean counterMessageReceived = false;
- private boolean gaugeMessageReceived = false;
- private boolean stringMessageReceived = false;
+ private volatile boolean counterMessageReceived = false;
+ private volatile boolean gaugeMessageReceived = false;
+ private volatile boolean stringMessageReceived = false;
// Match enum
public enum Match { do_not_match_0,
@@ -195,21 +195,33 @@
" has reached or exceeded the threshold");
echo("\t\tDerived Gauge = " + n.getDerivedGauge());
echo("\t\tTrigger = " + n.getTrigger());
- counterMessageReceived = true;
+
+ synchronized (this) {
+ counterMessageReceived = true;
+ notifyAll();
+ }
} else if (type.equals(MonitorNotification.
THRESHOLD_HIGH_VALUE_EXCEEDED)) {
echo("\t\t" + n.getObservedAttribute() +
" has reached or exceeded the high threshold");
echo("\t\tDerived Gauge = " + n.getDerivedGauge());
echo("\t\tTrigger = " + n.getTrigger());
- gaugeMessageReceived = true;
+
+ synchronized (this) {
+ gaugeMessageReceived = true;
+ notifyAll();
+ }
} else if (type.equals(MonitorNotification.
STRING_TO_COMPARE_VALUE_MATCHED)) {
echo("\t\t" + n.getObservedAttribute() +
" matches the string-to-compare value");
echo("\t\tDerived Gauge = " + n.getDerivedGauge());
echo("\t\tTrigger = " + n.getTrigger());
- stringMessageReceived = true;
+
+ synchronized (this) {
+ stringMessageReceived = true;
+ notifyAll();
+ }
} else {
echo("\t\tSkipping notification of type: " + type);
}
@@ -358,6 +370,17 @@
// Check if notification was received
//
+ synchronized (this) {
+ while (!counterMessageReceived) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ System.err.println("Got unexpected exception: " + e);
+ e.printStackTrace();
+ break;
+ }
+ }
+ }
if (counterMessageReceived) {
echo("\tOK: CounterMonitor notification received");
} else {
@@ -525,6 +548,17 @@
// Check if notification was received
//
+ synchronized (this) {
+ while (!gaugeMessageReceived) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ System.err.println("Got unexpected exception: " + e);
+ e.printStackTrace();
+ break;
+ }
+ }
+ }
if (gaugeMessageReceived) {
echo("\tOK: GaugeMonitor notification received");
} else {
@@ -680,6 +714,17 @@
// Check if notification was received
//
+ synchronized (this) {
+ while (!stringMessageReceived) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ System.err.println("Got unexpected exception: " + e);
+ e.printStackTrace();
+ break;
+ }
+ }
+ }
if (stringMessageReceived) {
echo("\tOK: StringMonitor notification received");
} else {
--- a/jdk/test/javax/management/monitor/CounterMonitorTest.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/javax/management/monitor/CounterMonitorTest.java Wed Jul 05 20:01:44 2017 +0200
@@ -43,9 +43,6 @@
// modulus number
private Number modulus = new Integer(7);
- // offset number
- private int offset = 0;
-
// difference mode flag
private boolean differenceModeFlag = true;
@@ -58,9 +55,6 @@
// counter values
private int[] values = new int[] {4, 6, 9, 11};
- // time to wait for notification (in seconds)
- private int timeout = 5;
-
// flag to notify that a message has been received
private volatile boolean messageReceived = false;
@@ -92,8 +86,9 @@
echo("\t\t" + n.getObservedAttribute() +
" has reached or exceeded the threshold");
echo("\t\tDerived Gauge = " + n.getDerivedGauge());
- messageReceived = true;
+
synchronized (this) {
+ messageReceived = true;
notifyAll();
}
} else {
@@ -205,22 +200,17 @@
}
/*
- * Wait until timeout reached
+ * Wait messageReceived to be true
*/
- void doWait() {
- for (int i = 0; i < timeout; i++) {
- echo("\tdoWait: Waiting for " + timeout + " seconds. " +
- "i = " + i + ", messageReceived = " + messageReceived);
- if (messageReceived) {
+ synchronized void doWait() {
+ while (!messageReceived) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ System.err.println("Got unexpected exception: " + e);
+ e.printStackTrace();
break;
}
- try {
- synchronized (this) {
- wait(1000);
- }
- } catch (InterruptedException e) {
- // OK: Ignore...
- }
}
}
--- a/jdk/test/javax/management/monitor/GaugeMonitorDeadlockTest.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/javax/management/monitor/GaugeMonitorDeadlockTest.java Wed Jul 05 20:01:44 2017 +0200
@@ -36,8 +36,9 @@
*/
import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
import java.util.concurrent.atomic.AtomicInteger;
-import javax.management.Attribute;
import javax.management.JMX;
import javax.management.MBeanServer;
import javax.management.Notification;
@@ -47,10 +48,16 @@
import javax.management.monitor.GaugeMonitorMBean;
public class GaugeMonitorDeadlockTest {
+ private static enum When {IN_GET_ATTRIBUTE, IN_NOTIFY};
+ private static long checkingTime;
public static void main(String[] args) throws Exception {
if (args.length != 1)
throw new Exception("Arg should be test number");
+ double factor = Double.parseDouble(System.getProperty("test.timeout.factor", "1.0"));
+ checkingTime = (long)factor*1000;
+ System.out.println("=== checkingTime = " + checkingTime + "ms");
+
int testNo = Integer.parseInt(args[0]) - 1;
TestCase test = testCases[testNo];
System.out.println("Test: " + test.getDescription());
@@ -58,8 +65,6 @@
System.out.println("Test passed");
}
- private static enum When {IN_GET_ATTRIBUTE, IN_NOTIFY};
-
private static abstract class TestCase {
TestCase(String description, When when) {
this.description = description;
@@ -98,16 +103,29 @@
monitorProxy.setNotifyLow(true);
monitorProxy.start();
+ System.out.println("=== Waiting observedProxy.getGetCount() to be "
+ + "changed, presumable deadlock if timeout?");
final int initGetCount = observedProxy.getGetCount();
- int getCount = initGetCount;
- for (int i = 0; i < 2000; i++) { // 2000 * 10 = 20 seconds
- getCount = observedProxy.getGetCount();
- if (getCount != initGetCount)
- break;
- Thread.sleep(10);
+ long checkedTime = System.currentTimeMillis();
+ long nowTime;
+ ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
+ while (observedProxy.getGetCount() == initGetCount) {
+ Thread.sleep(100);
+
+ nowTime = System.currentTimeMillis();
+ if (nowTime - checkedTime >= checkingTime) {
+ System.out.println("=== Checking deadlocked ...");
+ if (threadMXBean.findDeadlockedThreads() != null) {
+ for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) {
+ System.out.println(info);
+ }
+ throw new Error("Found deadlocked threads: "
+ + threadMXBean.findDeadlockedThreads().length);
+ }
+ checkedTime = System.currentTimeMillis();
+ }
}
- if (getCount <= initGetCount)
- throw new Exception("Test failed: presumable deadlock");
+
// This won't show up as a deadlock in CTRL-\ or in
// ThreadMXBean.findDeadlockedThreads(), because they don't
// see that thread A is waiting for thread B (B.join()), and
@@ -117,13 +135,13 @@
// so if we want to test notify behaviour we can trigger by
// exceeding the threshold.
if (when == When.IN_NOTIFY) {
+ final Thread testedThread = new Thread(sensitiveThing);
final AtomicInteger notifCount = new AtomicInteger();
final NotificationListener listener = new NotificationListener() {
public void handleNotification(Notification n, Object h) {
- Thread t = new Thread(sensitiveThing);
- t.start();
+ testedThread.start();
try {
- t.join();
+ testedThread.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
@@ -132,12 +150,36 @@
};
mbs.addNotificationListener(monitorName, listener, null, null);
observedProxy.setThing(1000);
- for (int i = 0; i < 2000 && notifCount.get() == 0; i++)
- Thread.sleep(10);
- if (notifCount.get() == 0)
- throw new Exception("Test failed: presumable deadlock");
+ System.out.println("=== Waiting notifications, presumable "
+ + "deadlock if timeout?");
+ long startTime = System.currentTimeMillis();
+ checkedTime = startTime;
+ while (notifCount.get() == 0) {
+ Thread.sleep(100);
+
+ nowTime = System.currentTimeMillis();
+ if (nowTime - checkedTime >= checkingTime) {
+ System.out.println("=== Checking the thread state ...");
+ if (testedThread.isAlive()) {
+ System.out.println("=== Waiting testedThread to die "
+ + "after " + (nowTime - startTime) + "ms");
+
+ ThreadInfo tinfo = threadMXBean.getThreadInfo(testedThread.getId());
+ if (Thread.State.BLOCKED.equals(tinfo.getThreadState())) {
+ for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) {
+ System.out.println(info);
+ }
+ } else {
+ System.out.println(tinfo);
+ }
+ } else {
+ System.out.println("=== The testedThread is dead as wished, "
+ + "the test must be passed soon.");
+ }
+ checkedTime = System.currentTimeMillis();
+ }
+ }
}
-
}
abstract void doSensitiveThing(GaugeMonitorMBean monitorProxy,
--- a/jdk/test/javax/management/monitor/NonComparableAttributeValueTest.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/javax/management/monitor/NonComparableAttributeValueTest.java Wed Jul 05 20:01:44 2017 +0200
@@ -39,7 +39,7 @@
public class NonComparableAttributeValueTest implements NotificationListener {
// Flag to notify that a message has been received
- private boolean messageReceived = false;
+ private volatile boolean messageReceived = false;
// MBean class
public class ObservedObject implements ObservedObjectMBean {
@@ -69,7 +69,11 @@
echo("\t\t" + n.getObservedAttribute() + " is null");
echo("\t\tDerived Gauge = " + n.getDerivedGauge());
echo("\t\tTrigger = " + n.getTrigger());
- messageReceived = true;
+
+ synchronized (this) {
+ messageReceived = true;
+ notifyAll();
+ }
} else {
echo("\t\tSkipping notification of type: " + type);
}
@@ -134,12 +138,9 @@
echo(">>> START the CounterMonitor");
counterMonitor.start();
- // Wait for granularity period (multiplied by 2 for sure)
- //
- Thread.sleep(granularityperiod * 2);
-
// Check if notification was received
//
+ doWait();
if (messageReceived) {
echo("\tOK: CounterMonitor notification received");
} else {
@@ -212,12 +213,9 @@
echo(">>> START the GaugeMonitor");
gaugeMonitor.start();
- // Wait for granularity period (multiplied by 2 for sure)
- //
- Thread.sleep(granularityperiod * 2);
-
// Check if notification was received
//
+ doWait();
if (messageReceived) {
echo("\tOK: GaugeMonitor notification received");
} else {
@@ -289,12 +287,9 @@
echo(">>> START the StringMonitor");
stringMonitor.start();
- // Wait for granularity period (multiplied by 2 for sure)
- //
- Thread.sleep(granularityperiod * 2);
-
// Check if notification was received
//
+ doWait();
if (messageReceived) {
echo("\tOK: StringMonitor notification received");
} else {
@@ -334,6 +329,21 @@
}
/*
+ * Wait messageReceived to be true
+ */
+ synchronized void doWait() {
+ while (!messageReceived) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ System.err.println("Got unexpected exception: " + e);
+ e.printStackTrace();
+ break;
+ }
+ }
+ }
+
+ /*
* Standalone entry point.
*
* Run the test and report to stdout.
--- a/jdk/test/javax/management/monitor/ReflectionExceptionTest.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/javax/management/monitor/ReflectionExceptionTest.java Wed Jul 05 20:01:44 2017 +0200
@@ -87,7 +87,11 @@
echo("\tObservedAttribute: " + mn.getObservedAttribute());
echo("\tDerivedGauge: " + mn.getDerivedGauge());
echo("\tTrigger: " + mn.getTrigger());
- messageReceived = true;
+
+ synchronized (this) {
+ messageReceived = true;
+ notifyAll();
+ }
}
}
}
@@ -135,12 +139,9 @@
echo(">>> START the CounterMonitor");
counterMonitor.start();
- // Wait for granularity period (multiplied by 2 for sure)
- //
- Thread.sleep(granularityperiod * 2);
-
// Check if notification was received
//
+ doWait();
if (messageReceived) {
echo("\tOK: CounterMonitor got RUNTIME_ERROR notification!");
} else {
@@ -203,12 +204,9 @@
echo(">>> START the GaugeMonitor");
gaugeMonitor.start();
- // Wait for granularity period (multiplied by 2 for sure)
- //
- Thread.sleep(granularityperiod * 2);
-
// Check if notification was received
//
+ doWait();
if (messageReceived) {
echo("\tOK: GaugeMonitor got RUNTIME_ERROR notification!");
} else {
@@ -270,12 +268,9 @@
echo(">>> START the StringMonitor");
stringMonitor.start();
- // Wait for granularity period (multiplied by 2 for sure)
- //
- Thread.sleep(granularityperiod * 2);
-
// Check if notification was received
//
+ doWait();
if (messageReceived) {
echo("\tOK: StringMonitor got RUNTIME_ERROR notification!");
} else {
@@ -349,8 +344,23 @@
}
}
+ /*
+ * Wait messageReceived to be true
+ */
+ synchronized void doWait() {
+ while (!messageReceived) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ System.err.println("Got unexpected exception: " + e);
+ e.printStackTrace();
+ break;
+ }
+ }
+ }
+
// Flag to notify that a message has been received
- private boolean messageReceived = false;
+ private volatile boolean messageReceived = false;
private MBeanServer server;
private ObjectName obsObjName;
--- a/jdk/test/javax/management/monitor/RuntimeExceptionTest.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/javax/management/monitor/RuntimeExceptionTest.java Wed Jul 05 20:01:44 2017 +0200
@@ -86,7 +86,11 @@
echo("\tObservedAttribute: " + mn.getObservedAttribute());
echo("\tDerivedGauge: " + mn.getDerivedGauge());
echo("\tTrigger: " + mn.getTrigger());
- messageReceived = true;
+
+ synchronized (this) {
+ messageReceived = true;
+ notifyAll();
+ }
}
}
}
@@ -134,12 +138,9 @@
echo(">>> START the CounterMonitor");
counterMonitor.start();
- // Wait for granularity period (multiplied by 2 for sure)
- //
- Thread.sleep(granularityperiod * 2);
-
// Check if notification was received
//
+ doWait();
if (messageReceived) {
echo("\tOK: CounterMonitor got RUNTIME_ERROR notification!");
} else {
@@ -202,12 +203,9 @@
echo(">>> START the GaugeMonitor");
gaugeMonitor.start();
- // Wait for granularity period (multiplied by 2 for sure)
- //
- Thread.sleep(granularityperiod * 2);
-
// Check if notification was received
//
+ doWait();
if (messageReceived) {
echo("\tOK: GaugeMonitor got RUNTIME_ERROR notification!");
} else {
@@ -269,12 +267,9 @@
echo(">>> START the StringMonitor");
stringMonitor.start();
- // Wait for granularity period (multiplied by 2 for sure)
- //
- Thread.sleep(granularityperiod * 2);
-
// Check if notification was received
//
+ doWait();
if (messageReceived) {
echo("\tOK: StringMonitor got RUNTIME_ERROR notification!");
} else {
@@ -347,8 +342,23 @@
}
}
+ /*
+ * Wait messageReceived to be true
+ */
+ synchronized void doWait() {
+ while (!messageReceived) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ System.err.println("Got unexpected exception: " + e);
+ e.printStackTrace();
+ break;
+ }
+ }
+ }
+
// Flag to notify that a message has been received
- private boolean messageReceived = false;
+ private volatile boolean messageReceived = false;
private MBeanServer server;
private ObjectName obsObjName;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JWindow/ShapedAndTranslucentWindows/Common.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2014, 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 javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.geom.Area;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.security.SecureRandom;
+
+public abstract class Common {
+
+ ExtendedRobot robot;
+ Class<? extends JFrame> windowClass;
+ JFrame background;
+ BufferedImage foreground;
+ Window window;
+ volatile boolean gradientBackgroundEnabled = false;
+ volatile int gradientWidth = 255;
+ volatile int gradientHeight = 255;
+
+ float opacity = 1.0f;
+ float perPixelTranslucency = 1.0f;
+ static Color BG_COLOR = Color.BLUE;
+ static Color FG_COLOR = Color.RED;
+ static final int delay = 1000;
+ static final SecureRandom random = new SecureRandom();
+ static final int dl = 100;
+ static final Class[] WINDOWS_TO_TEST = { JWindow.class, JFrame.class, JDialog.class };
+
+ volatile int clicked;
+
+ public Common(Class windowClass, float opacity, float perPixelTranslucency, boolean gradient) throws Exception {
+ this.gradientBackgroundEnabled = gradient;
+ this.perPixelTranslucency = perPixelTranslucency;
+ this.opacity = opacity;
+ robot = new ExtendedRobot();
+ this.windowClass = windowClass;
+ EventQueue.invokeAndWait(this::initBackgroundFrame);
+ EventQueue.invokeAndWait(this::initGUI);
+ }
+
+ public Common(Class windowClass) throws Exception {
+ this(windowClass, 1.0f, 1.0f, false);
+ }
+
+ public Common(Class windowClass, boolean gradient) throws Exception {
+ this(windowClass, 1.0f, 1.0f, gradient);
+ }
+
+ public abstract void doTest() throws Exception;
+
+ public void dispose() {
+ window.dispose();
+ background.dispose();
+ }
+
+ public void applyShape() {};
+
+ public void applyDynamicShape() {
+ final Area a = new Area();
+ Dimension size = window.getSize();
+ for (int x = 0; x < 3; x++) {
+ for (int y = 0; y < 3; y++) {
+ a.add(new Area(new Rectangle2D.Double(
+ x * size.getWidth() / 17*6, y * size.getHeight() / 17*6,
+ size.getWidth() / 17*5, size.getHeight() / 17*5)));
+ }
+ }
+ window.setShape(a);
+ }
+
+ public BufferedImage getForegroundWindow() throws Exception {
+ final BufferedImage f[] = new BufferedImage[1];
+ EventQueue.invokeAndWait( () -> {
+ f[0] = new BufferedImage(window.getWidth(),
+ window.getHeight(), BufferedImage.TYPE_INT_RGB);
+ window.printAll(f[0].createGraphics());
+ });
+ robot.waitForIdle(delay);
+ return f[0];
+ }
+
+ public static boolean checkTranslucencyMode(GraphicsDevice.WindowTranslucency mode) {
+
+ if (!GraphicsEnvironment
+ .getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice()
+ .isWindowTranslucencySupported(mode)){
+ System.out.println(mode+" translucency mode isn't supported");
+ return false;
+ } else {
+ return true;
+ }
+
+ }
+
+ public void applyAppDragNResizeSupport() {
+ MouseAdapter m = new MouseAdapter() {
+
+ private Point dragOrigin = null;
+ private Dimension origSize = null;
+ private Point origLoc = null;
+ private boolean left = false;
+ private boolean top = false;
+ private boolean bottom = false;
+ private boolean right = false;
+
+ public void mousePressed(MouseEvent e) {
+ dragOrigin = e.getLocationOnScreen();
+ origSize = window.getSize();
+ origLoc = window.getLocationOnScreen();
+ right = (origLoc.x + window.getWidth() - dragOrigin.x) < 5;
+ left = !right && dragOrigin.x - origLoc.x < 5;
+ bottom = (origLoc.y + window.getHeight() - dragOrigin.y) < 5;
+ top = !bottom && dragOrigin.y - origLoc.y < 5;
+ }
+
+ public void mouseReleased(MouseEvent e) { resize(e); }
+ public void mouseDragged(MouseEvent e) { resize(e); }
+
+ void resize(MouseEvent e) {
+ Point dragDelta = e.getLocationOnScreen();
+ dragDelta.translate(-dragOrigin.x, -dragOrigin.y);
+ Point newLoc = new Point(origLoc);
+ newLoc.translate(dragDelta.x, dragDelta.y);
+ Dimension newSize = new Dimension(origSize);
+ if (left || right) {
+ newSize.width += right ? dragDelta.x : -dragDelta.x;
+ }
+ if (top || bottom) {
+ newSize.height += bottom ? dragDelta.y : -dragDelta.y;
+ }
+ if (right || (top || bottom) && !left) {
+ newLoc.x = origLoc.x;
+ }
+ if (bottom || (left || right) && !top) {
+ newLoc.y = origLoc.y;
+ }
+ window.setBounds(newLoc.x, newLoc.y, newSize.width, newSize.height);
+ }
+ };
+ for (Component comp : window.getComponents()) {
+ comp.addMouseListener(m);
+ comp.addMouseMotionListener(m);
+ }
+
+ window.addMouseListener(m);
+ window.addMouseMotionListener(m);
+ }
+
+ public void checkTranslucentShape() throws Exception {
+ foreground = getForegroundWindow();
+ Point[] points = new Point[4];
+
+ Dimension size = window.getSize();
+ Point location = window.getLocationOnScreen();
+
+ points[0] = new Point(20, 20);
+ points[1] = new Point(20, size.height-20);
+ points[2] = new Point(size.width-20, 20);
+ points[3] = new Point(size.width-20, size.height-20);
+
+ for (Point p : points){
+ p.translate(location.x, location.y);
+ Color actual = robot.getPixelColor(p.x, p.y);
+ if (actual.equals(BG_COLOR)|| actual.equals(FG_COLOR))
+ throw new RuntimeException("Error in point "+p+": "+actual+" equals to foreground or background color");
+ else
+ System.out.println("OK with foreground point "+p);
+ }
+ }
+
+ public void checkDynamicShape() throws Exception {
+ Point[] points = new Point[4];
+
+ Dimension size = window.getSize();
+
+ int blockSizeX = (int) (size.getWidth() / 17);
+ int blockSizeY = (int) (size.getHeight() / 17);
+
+ // background
+ points[0] = new Point((int) (blockSizeX * 5.5), (int) (blockSizeY * 5.5));
+ points[1] = new Point((int) (size.getWidth() - blockSizeX * 5.5), (int) (size.getHeight() - blockSizeY * 5.5));
+ points[2] = new Point((int) (blockSizeX * 5.5), (int) (size.getHeight() - blockSizeY * 5.5));
+ points[3] = new Point((int) (size.getWidth() - blockSizeX * 5.5), (int) (blockSizeY * 5.5));
+ checkShape(points, true);
+
+ // foreground
+ if (opacity < 1.0f){
+ checkTranslucentShape();
+ } else {
+ points[0] = new Point(3 * blockSizeX, 3 * blockSizeY);
+ points[1] = new Point(14 * blockSizeX, 14 * blockSizeY);
+ points[2] = new Point(3 * blockSizeX, 14 * blockSizeY);
+ points[3] = new Point(14 * blockSizeX, 3 * blockSizeY);
+ checkShape(points, false);
+ }
+ }
+
+ public void checkShape(Point[] points, boolean areBackgroundPoints) throws Exception {
+
+ Point location = window.getLocationOnScreen();
+
+ for (Point p : points) {
+ p.translate(location.x, location.y);
+ Color pixel = robot.getPixelColor(p.x, p.y);
+ if (areBackgroundPoints) {
+ if (pixel.getRed() != 0
+ || pixel.getGreen() != 0 )
+ throw new RuntimeException("Background point " + p +
+ " color " + pixel +
+ " does not equal to background color " + BG_COLOR);
+ else
+ System.out.println("OK with background point " + p);
+ } else {
+ if (pixel.equals(BG_COLOR))
+ throw new RuntimeException("Foreground point " + p +
+ " color " + pixel +
+ " equals to background color " + BG_COLOR);
+ else
+ System.out.println("OK with foreground point " + p);
+ }
+ }
+ }
+
+ public void initBackgroundFrame() {
+ background = new JFrame();
+ background.setUndecorated(true);
+ background.getContentPane().setBackground(BG_COLOR);
+ background.setSize(500, 500);
+ background.setLocation(dl, dl);
+ background.setVisible(true);
+ }
+
+ public void initGUI() {
+ Container contentPane;
+ if (windowClass.equals(Frame.class)) {
+ window = new JFrame();
+ ((JFrame) window).setUndecorated(true);
+ contentPane = ((JFrame) window).getContentPane();
+ } else if (windowClass.equals(Dialog.class)) {
+ window = new JDialog(background);
+ ((JDialog) window).setUndecorated(true);
+ contentPane = ((JDialog) window).getContentPane();
+ } else {
+ window = new JWindow(background);
+ contentPane = ((JWindow) window).getContentPane();
+ }
+
+ if (perPixelTranslucency < 1.0f) {
+ contentPane.setBackground(colorWithOpacity(FG_COLOR, perPixelTranslucency));
+ window.setBackground(colorWithOpacity(FG_COLOR, perPixelTranslucency));
+ } else {
+ contentPane.setBackground(FG_COLOR);
+ window.setBackground(FG_COLOR);
+ }
+
+ window.setLocation(2 * dl, 2 * dl);
+ window.setSize(255, 255);
+ window.setPreferredSize(new Dimension(255, 255));
+ createSwingComponents();
+ if (opacity < 1.0f)
+ window.setOpacity(opacity);
+
+ window.addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent e) {
+ applyShape();
+ }
+ });
+ applyShape();
+ window.setVisible(true);
+ applyAppDragNResizeSupport();
+ window.toFront();
+ }
+
+ public void createSwingComponents() {
+ Container contentPane;
+ if (gradientBackgroundEnabled) {
+ JPanel jPanel = new JPanel() {
+ @Override
+ protected void paintComponent(Graphics g) {
+ if (g instanceof Graphics2D) {
+ Color background = Color.RED;
+ Paint p = new GradientPaint(0.0f, 0.0f, colorWithOpacity(background, 0),
+ 0.0f, gradientHeight - 3, colorWithOpacity(background, 1), true);
+ Graphics2D g2d = (Graphics2D) g;
+ g2d.setPaint(p);
+ g2d.fillRect(0, 3, gradientWidth, gradientHeight - 3);
+ } else {
+ super.paintComponent(g);
+ }
+ }
+ };
+ jPanel.setBorder(new EmptyBorder(15, 5, 5, 5));
+ jPanel.setOpaque(false);
+
+ contentPane = jPanel;
+
+ RootPaneContainer.class.cast(window).setContentPane(contentPane);
+ } else {
+ contentPane = RootPaneContainer.class.cast(window).getContentPane();
+ }
+ contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
+
+ JButton button = new JButton("JButton");
+ window.add(button);
+
+ JTextArea textArea = new JTextArea("JTextArea");
+ window.add(textArea);
+
+ JCheckBox checkbox = new JCheckBox("JCheckBox");
+ checkbox.setOpaque(false);
+ window.add(checkbox);
+
+ JComboBox comboBox = new JComboBox(new String[]{"JComboBox", "Some item"});
+ window.add(comboBox);
+
+ JLabel label = new JLabel("JLabel");
+ window.add(label);
+
+ JTextField textField = new JTextField("JTextField");
+ window.add(textField);
+
+ JPanel panel = new JPanel();
+ panel.setOpaque(false);
+ window.add(panel);
+
+ JComboBox comboBox2 = new JComboBox(new String[]{"JComboBox2", "Another item"});
+ window.add(comboBox2);
+
+ JRadioButton radioButton = new JRadioButton("JRadioButton");
+ radioButton.setOpaque(false);
+ window.add(radioButton);
+ }
+
+ Color colorWithOpacity(Color color, float opacity) {
+ return new Color(color.getColorSpace(), color.getColorComponents(null), opacity);
+ }
+
+ public void checkTranslucent() throws Exception {
+ checkTranslucentShape();
+
+ // Drag
+ Point location = window.getLocationOnScreen();
+ robot.dragAndDrop(location.x + 30, location.y + 5, location.x + dl + random.nextInt(dl), location.y + random.nextInt(dl));
+ robot.waitForIdle(delay);
+ checkTranslucentShape();
+
+ // Resize
+ location = window.getLocationOnScreen();
+ robot.dragAndDrop(location.x + 4, location.y + 4, location.x + random.nextInt(2*dl)-dl, location.y + random.nextInt(2*dl)-dl);
+ robot.waitForIdle(delay);
+ checkTranslucentShape();
+
+ EventQueue.invokeAndWait(this::dispose);
+ }
+
+ public void checkDynamic() throws Exception {
+ checkDynamicShape();
+
+ // Drag
+ Point location = window.getLocationOnScreen();
+ robot.dragAndDrop(location.x + 30, location.y + 5, location.x + dl + random.nextInt(dl), location.y + random.nextInt(dl));
+ robot.waitForIdle(delay);
+ checkDynamicShape();
+
+ // Resize
+ location = window.getLocationOnScreen();
+ robot.dragAndDrop(location.x + 4, location.y + 4, location.x + random.nextInt(2*dl)-dl, location.y + random.nextInt(2*dl)-dl);
+ robot.waitForIdle(delay);
+ checkDynamicShape();
+
+ EventQueue.invokeAndWait(this::dispose);
+ }
+
+ void checkClick(int x, int y, int flag) throws Exception {
+
+ System.out.println("Trying to click point " + x + ", " + y + ", looking for " + flag + " flag to trigger.");
+
+ clicked = 0;
+ robot.mouseMove(x, y);
+ robot.click();
+
+ for (int i = 0; i < 100; i++)
+ if ((clicked & (1 << flag)) == 0)
+ robot.delay(50);
+ else
+ break;
+
+ if ((clicked & (1 << flag)) == 0)
+ throw new RuntimeException("FAIL: Flag " + flag + " is not triggered for point " + x + ", " + y + "!");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucent.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2010, 2014, 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.*;
+
+/*
+ * @test
+ * @summary Check if a per-pixel translucent window is dragged and resized
+ * by mouse correctly.
+ * Test Description: Check if PERPIXEL_TRANSLUCENT translucency type is supported
+ * on the current platform. Proceed if they are supported. Create a window
+ * with some components in it, make window undecorated, apply translucent
+ * background of 0.5. Drag and resize the window using AWT Robot and verify
+ * that translucency is correctly applied with pixels checking. Make the
+ * window appear on top of a known background. Repeat this for JWindow,
+ * JDialog, JFrame.
+ * Expected Result: If PERPIXEL_TRANSLUCENT translucency type is supported, the
+ * window should appear with the translucency. Only window background
+ * should be translucent, all the controls should be opaque.
+ * @author mrkam
+ * @library ../../../../lib/testlibrary
+ * @build Common ExtendedRobot
+ * @run main PerPixelTranslucent
+ */
+
+public class PerPixelTranslucent extends Common {
+
+ public static void main(String[] ignored) throws Exception {
+ if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT))
+ for (Class<Window> windowClass: WINDOWS_TO_TEST)
+ new PerPixelTranslucent(windowClass).doTest();
+ }
+
+ public PerPixelTranslucent(Class windowClass) throws Exception {
+ super(windowClass, 1.0f, 0.5f, false);
+ }
+
+ public void doTest() throws Exception {
+ robot.waitForIdle(delay);
+ checkTranslucent();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentCanvas.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2010, 2014, 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.*;
+import javax.swing.*;
+import java.awt.image.BufferedImage;
+
+/*
+ * @test
+ * @summary Check if a per-pixel translucent window shows up with correct translucency
+ * @author mrkam
+ * @library ../../../../lib/testlibrary
+ * @build Common ExtendedRobot
+ * @run main PerPixelTranslucentCanvas
+ */
+
+public class PerPixelTranslucentCanvas extends Common {
+
+ JPanel center;
+ Color OVAL_COLOR = Color.BLUE;
+
+ public static void main(String[] ignored) throws Exception {
+ FG_COLOR = new Color(200, 0, 0, 100);
+ BG_COLOR = Color.GREEN;
+ for (Class<Window> windowClass: WINDOWS_TO_TEST)
+ new PerPixelTranslucentCanvas(windowClass).doTest();
+ }
+
+ public PerPixelTranslucentCanvas(Class windowClass) throws Exception {
+ super(windowClass);
+ }
+
+ @Override
+ public void createSwingComponents() {
+ Container contentPane = RootPaneContainer.class.cast(window).getContentPane();
+ BorderLayout bl = new BorderLayout(10, 10);
+ contentPane.setLayout(bl);
+
+ JLabel label = new JLabel("North", new ImageIcon(
+ new BufferedImage(30, 30, BufferedImage.TYPE_INT_RGB)), SwingConstants.CENTER);
+ contentPane.add(label, BorderLayout.NORTH);
+
+ JButton button = new JButton("West");
+ contentPane.add(button, BorderLayout.WEST);
+
+ center = new JPanel() {
+ @Override
+ public void paint(Graphics g) {
+ g.setColor(OVAL_COLOR);
+ g.fillOval(0, 0, getWidth(), getHeight());
+ }
+ };
+ contentPane.add(center, BorderLayout.CENTER);
+
+ JTextField jTextField = new JTextField("South");
+ contentPane.add(jTextField, BorderLayout.SOUTH);
+ }
+
+ @Override
+ public void doTest() throws Exception {
+ robot.waitForIdle(delay);
+
+ Rectangle bounds = center.getBounds();
+ Point loc = center.getLocationOnScreen();
+
+ final int x = loc.x + bounds.width / 2;
+ final int y = loc.y + bounds.height / 2;
+
+ Color color = robot.getPixelColor(x, y);
+ if (OVAL_COLOR.getRGB() != color.getRGB())
+ throw new RuntimeException("bounds = " + bounds + "\n" +
+ "loc = " + loc + "\n" +
+ "background loc = " + background.getX() + ", " + background.getY() + "\n" +
+ "so middle point over background is " + (x - background.getX()) + ", " + (y - background.getY()) + "\n" +
+ "Oval is not opaque in the middle point (" + x + ", " + y + ", " + color + ")");
+
+ color = robot.getPixelColor(loc.x - 5, loc.y - 5);
+ if (FG_COLOR.getRGB() == color.getRGB())
+ throw new RuntimeException("Background is not translucent (" + color + ")");
+
+ EventQueue.invokeAndWait(this::dispose);
+ robot.waitForIdle();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentGradient.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2010, 2014, 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.*;
+
+/*
+ * @test
+ * @bug 8032644
+ * @summary Check if a per-pixel translucent window is dragged and resized by
+ * mouse correctly
+ * Test Description: Check if PERPIXEL_TRANSLUCENT translucency type is supported
+ * on the current platform. Proceed if they are supported. Create a window
+ * with some components in it, make window undecorated, apply translucent
+ * background of 0 and have a gradient painted as background from
+ * fully-transparent to fully-opaque in componentResized listener. Drag and
+ * resize the window using AWT Robot and verify that translucency is
+ * correctly applied with pixels checking. Make the window appear on top of
+ * a known background. Repeat this for JWindow, JDialog, JFrame.
+ * Expected Result: If PERPIXEL_TRANSLUCENT translucency type is supported,
+ * the window should appear as specified with the translucency. Only window
+ * background should be translucent, all the controls should be opaque.
+ * @author mrkam
+ * @library ../../../../lib/testlibrary
+ * @build Common ExtendedRobot
+ * @run main PerPixelTranslucentGradient
+ */
+
+public class PerPixelTranslucentGradient extends Common {
+
+ public static void main(String[] ignored) throws Exception {
+ if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT))
+ for (Class<Window> windowClass: WINDOWS_TO_TEST)
+ new PerPixelTranslucentGradient(windowClass).doTest();
+ }
+
+ public PerPixelTranslucentGradient(Class windowClass) throws Exception {
+ super(windowClass, 1.0f, 0f, true);
+ }
+
+ public void doTest() throws Exception {
+ robot.waitForIdle(delay);
+ checkTranslucent();
+ }
+
+ @Override
+ public void applyShape() {
+ gradientWidth = window.getWidth();
+ gradientHeight = window.getHeight();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentSwing.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2010, 2014, 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 javax.swing.*;
+import java.awt.*;
+
+/*
+ * @test
+ * @summary Check if a per-pixel translucent window shows only the area having
+ * opaque pixels
+ * Test Description: Check if PERPIXEL_TRANSLUCENT Translucency type is supported
+ * on the current platform. Proceed if it is supported. Create a swing window
+ * with some swing components in it and a transparent background (alpha 0.0).
+ * Bring this window on top of a known background. Do this test for JFrame,
+ * JWindow and JDialog
+ * Expected Result: Only the components present in the window must be shown. Other
+ * areas of the window must be transparent so that the background shows
+ * @author mrkam
+ * @library ../../../../lib/testlibrary
+ * @build Common ExtendedRobot
+ * @run main PerPixelTranslucentSwing
+ */
+
+public class PerPixelTranslucentSwing extends Common {
+
+ JButton north;
+
+ public static void main(String[] ignored) throws Exception {
+ FG_COLOR = new Color(200, 0, 0, 0);
+ if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT))
+ for (Class<Window> windowClass: WINDOWS_TO_TEST)
+ new PerPixelTranslucentSwing(windowClass).doTest();
+ }
+
+ public PerPixelTranslucentSwing(Class windowClass) throws Exception {
+ super(windowClass);
+ }
+
+ @Override
+ public void createSwingComponents() {
+ Container contentPane = RootPaneContainer.class.cast(window).getContentPane();
+ BorderLayout bl = new BorderLayout(10, 5);
+ contentPane.setLayout(bl);
+
+ north = new JButton("North");
+ contentPane.add(north, BorderLayout.NORTH);
+
+ JList center = new JList(new String[] {"Center"});
+ contentPane.add(center, BorderLayout.CENTER);
+
+ JTextField south = new JTextField("South");
+ contentPane.add(south, BorderLayout.SOUTH);
+
+ window.pack();
+ window.setVisible(true);
+
+ north.requestFocus();
+ }
+
+ @Override
+ public void doTest() throws Exception {
+ robot.waitForIdle(delay);
+
+ // Check for background translucency
+ Rectangle bounds = north.getBounds();
+ Point loc = north.getLocationOnScreen();
+
+ Color color = robot.getPixelColor(loc.x + bounds.width / 2, loc.y + bounds.height + 3);
+ System.out.println(color);
+ if (FG_COLOR.getRGB() == color.getRGB())
+ throw new RuntimeException("Background is not translucent (" + color + ")");
+
+ EventQueue.invokeAndWait(this::dispose);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JWindow/ShapedAndTranslucentWindows/SetShapeAndClickSwing.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2010, 2014, 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 javax.swing.*;
+import java.awt.*;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.geom.Area;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Rectangle2D;
+
+/*
+ * @test
+ * @summary Check if a window set with shape clips the contents
+ * Test Description: Check if PERPIXEL_TRANSPARENT translucency type is supported
+ * by the current platform. Proceed if it is supported. Apply different types
+ * of shapes on a Window which contains some awt components. Shape should be
+ * applied in such a way that some components are partially clipped off. Check
+ * if the components appear only partially and events work correctly for those
+ * components - i.e. events occur only on the areas which appear and do not
+ * occur on the clipped off areas. Events should be checked by clicking on the
+ * visible and clipped regions. Repeat this for Window, Dialog and Frame.
+ * Expected Result: If PERPIXEL_TRANSPARENT translucency type is supported, clicking
+ * on clipped region should deliver the event to the background (it should be
+ * another Window behind the test window)
+ * @author mrkam
+ * @library ../../../../lib/testlibrary
+ * @build Common ExtendedRobot
+ * @run main SetShapeAndClickSwing
+ */
+
+public class SetShapeAndClickSwing extends Common {
+
+ Component south, center, north;
+
+ public static void main(String[] args) throws Exception {
+ if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSPARENT))
+ for (Class<Window> windowClass: WINDOWS_TO_TEST)
+ new SetShapeAndClickSwing(windowClass).doTest();
+ }
+
+ public SetShapeAndClickSwing(Class windowClass) throws Exception {
+ super(windowClass);
+ }
+
+ @Override
+ public void initBackgroundFrame() {
+ super.initBackgroundFrame();
+ background.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ clicked |= 1 << 0;
+ }
+ });
+ }
+
+ @Override
+ public void createSwingComponents() {
+ window.setSize(200,200);
+ window.setLayout(new BorderLayout());
+
+ south = new JLabel("South");
+ south.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ clicked |= 1 << 3;
+ }
+ });
+ window.add(south, BorderLayout.SOUTH);
+
+ center = new JList();
+ center.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ clicked |= 1 << 2;
+ }
+ });
+ window.add(center, BorderLayout.CENTER);
+
+ north = new JTextField("North");
+ north.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ clicked |= 1 << 1;
+ }
+ });
+ window.add(north, BorderLayout.NORTH);
+ }
+
+ @Override
+ public void doTest() throws Exception {
+
+ robot.waitForIdle();
+
+ Point wls = window.getLocationOnScreen();
+ Point ls;
+ int y;
+ ls = north.getLocationOnScreen();
+ checkClick(ls.x + north.getWidth() / 3, ls.y + north.getHeight() / 2, 1);
+
+ ls = center.getLocationOnScreen();
+ checkClick(ls.x + center.getWidth() * 3 / 4, ls.y + center.getHeight() * 3 / 4, 2);
+
+ ls = south.getLocationOnScreen();
+ checkClick(ls.x + south.getWidth() * 2 / 3, ls.y + south.getHeight() / 2, 3);
+
+ ls = center.getLocationOnScreen();
+ checkClick(ls.x + center.getWidth() / 4, ls.y + center.getHeight() / 4, 2);
+
+ ls = north.getLocationOnScreen();
+ y = ls.y + north.getHeight() / 2;
+ checkClick(wls.x + 200 - (y - wls.y), y, 0);
+
+ EventQueue.invokeAndWait(window::toFront);
+ robot.waitForIdle();
+
+ ls = center.getLocationOnScreen();
+ y = ls.y + center.getHeight() / 2;
+ checkClick(wls.x + 200 - (y - wls.y), y, 0);
+
+ EventQueue.invokeAndWait(window::toFront);
+ robot.waitForIdle();
+
+ ls = south.getLocationOnScreen();
+ y = ls.y + south.getHeight() / 2;
+ checkClick(wls.x + 200 - (y - wls.y), y, 0);
+
+ EventQueue.invokeAndWait(window::dispose);
+ EventQueue.invokeAndWait(background::dispose);
+
+ robot.waitForIdle();
+ }
+
+ @Override
+ public void applyShape() {
+ Area shape = new Area(new Rectangle2D.Float(0, 0, 200, 200));
+ GeneralPath gp;
+ gp = new GeneralPath();
+ gp.moveTo(190, 0);
+ gp.lineTo(200, 0);
+ gp.lineTo(200, 10);
+ gp.lineTo(10, 200);
+ gp.lineTo(0, 200);
+ gp.lineTo(0, 190);
+ gp.closePath();
+ shape.subtract(new Area(gp));
+
+ window.setShape(shape);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedPerPixelTranslucentGradient.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2010, 2014, 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.*;
+
+/*
+ * @test
+ * @bug 7043845
+ * @summary Check if shaped and per-pixel translucent window is dragged and
+ * resized by mouse correctly.
+ * Test Description: Check if PERPIXEL_TRANSLUCENT and PERPIXEL_TRANSPARENT
+ * translucency types are supported on the current platform. Proceed if
+ * they are supported. Create a window with some components in it, make
+ * window undecorated, apply shape in componentResized listener. The shape
+ * should match the window size; apply translucent background of 0 and have
+ * a gradient painted as background from fully-transparent to fully-opaque
+ * in componentResized listener. Drag and resize the window using AWT Robot
+ * and verify that shape and translucency are correctly applied with pixels
+ * checking. Make the window appear on top of a known background. Repeat
+ * this for JWindow, JDialog, JFrame.
+ * Expected Result: If PERPIXEL_TRANSLUCENT and PERPIXEL_TRANSPARENT translucency
+ * types are supported, the window should appear as specified with the
+ * expected shape and translucency. Window background should have
+ * translucent gradient in parts that are not clipped by shape, all the
+ * controls should be opaque.
+ * @author mrkam
+ * @library ../../../../lib/testlibrary
+ * @build Common ExtendedRobot
+ * @run main ShapedPerPixelTranslucentGradient
+ */
+
+public class ShapedPerPixelTranslucentGradient extends Common {
+
+ public static void main(String[] ignored) throws Exception {
+ if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT)
+ && checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSPARENT))
+ for (Class<Window> windowClass: WINDOWS_TO_TEST)
+ new ShapedPerPixelTranslucentGradient(windowClass).doTest();
+ }
+
+ public ShapedPerPixelTranslucentGradient(Class windowClass) throws Exception {
+ super(windowClass, 1.0f, 0f, true);
+ }
+
+ public void doTest() throws Exception {
+ robot.waitForIdle(delay);
+ checkDynamic();
+ }
+
+ @Override
+ public void applyShape() {
+ applyDynamicShape();
+ gradientWidth = window.getWidth();
+ gradientHeight = window.getHeight();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedTranslucentPerPixelTranslucentGradient.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2010, 2014, 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.*;
+
+/*
+ * @test
+ * @summary Check if shaped, translucent and per-pixel translucent window is
+ * dragged and resized by mouse correctly.
+ * Test Description: Check if PERPIXEL_TRANSLUCENT, TRANSLUCENT and
+ * PERPIXEL_TRANSPARENT translucency types are supported on the current
+ * platform. Proceed if they are supported. Create a window with some
+ * components in it, make window undecorated, apply shape in componentResized
+ * listener. The shape should match the window size; apply opacity of 0.7,
+ * apply translucent background of 0 and have a gradient painted as
+ * background from fully-transparent to fully-opaque in componentResized
+ * listener. Drag and resize the window using AWT Robot and verify that
+ * shape and translucency are correctly applied with pixels checking. Make
+ * the window appear on top of a known background. Repeat this for JWindow,
+ * JDialog, JFrame.
+ * Expected Result: If PERPIXEL_TRANSLUCENT, TRANSLUCENT and PERPIXEL_TRANSPARENT
+ * translucency types are supported, the window should appear as specified
+ * with the expected shape and translucency. Window background should have
+ * translucent gradient in parts that are not clipped by shape, all the
+ * controls should be equally translucent.
+ * @author mrkam
+ * @library ../../../../lib/testlibrary
+ * @build Common ExtendedRobot
+ * @run main ShapedTranslucentPerPixelTranslucentGradient
+ */
+
+public class ShapedTranslucentPerPixelTranslucentGradient extends Common {
+
+ public static void main(String[] ignored) throws Exception {
+ if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT)
+ && checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSPARENT)
+ && checkTranslucencyMode(GraphicsDevice.WindowTranslucency.TRANSLUCENT))
+ for (Class<Window> windowClass: WINDOWS_TO_TEST)
+ new ShapedTranslucentPerPixelTranslucentGradient(windowClass).doTest();
+ }
+
+ public ShapedTranslucentPerPixelTranslucentGradient(Class windowClass) throws Exception {
+ super(windowClass, 0.7f, 0f, true);
+ }
+
+ public void doTest() throws Exception {
+ robot.waitForIdle(delay);
+ checkDynamic();
+ }
+
+ @Override
+ public void applyShape() {
+ applyDynamicShape();
+ gradientWidth = window.getWidth();
+ gradientHeight = window.getHeight();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentJComboBox.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2010, 2014, 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 javax.swing.*;
+import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+/*
+ * @test
+ * @bug 8024627
+ * @summary Check if a JComboBox present in a window set with opacity less than
+ * 1.0 shows a translucent drop down
+ * Test Description: Check if TRANSLUCENT translucency type is supported on the
+ * current platform. Proceed if supported. Show a window which contains an
+ * JComboBox and set with opacity less than 1.0. Another Window having a canvas
+ * component drawn with an image can be used as the background for the test
+ * window. Click on the ComboBox to show the drop down. Check if the drop down
+ * appears translucent. Repeat this for JWindow, JDialog and JFrame
+ * Expected Result: If TRANSLUCENT Translucency type is supported, the drop down
+ * should appear translucent.
+ * @author mrkam
+ * @library ../../../../lib/testlibrary
+ * @build Common ExtendedRobot
+ * @run main TranslucentJComboBox
+ */
+
+public class TranslucentJComboBox extends Common {
+
+ JComponent south;
+ JComponent center;
+ JPanel north;
+ volatile boolean southClicked = false;
+
+ public static void main(String[] args) throws Exception {
+ if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.TRANSLUCENT))
+ for (Class<Window> windowClass: WINDOWS_TO_TEST)
+ new TranslucentJComboBox(windowClass).doTest();
+ }
+
+ public TranslucentJComboBox(Class windowClass) throws Exception {
+ super(windowClass, 0.3f, 1.0f, false);
+ }
+
+ @Override
+ public void initBackgroundFrame() {
+ super.initBackgroundFrame();
+ }
+
+ @Override
+ public void createSwingComponents() {
+ Container contentPane = RootPaneContainer.class.cast(window).getContentPane();
+ window.setLayout(new BorderLayout());
+
+ north = new JPanel();
+ contentPane.add(north, BorderLayout.NORTH);
+
+ center = new JList(new String [] { "Center" });
+ contentPane.add(center, BorderLayout.CENTER);
+
+ JComboBox jComboBox = new JComboBox();
+ for(int i = 0; i < 20; i++) {
+ jComboBox.addItem("item " + i);
+ }
+ south = jComboBox;
+
+ south.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ southClicked = true;
+ }
+ });
+ contentPane.add(south, BorderLayout.SOUTH);
+ }
+
+
+ @Override
+ public void doTest() throws Exception {
+ robot.waitForIdle(delay);
+ // Make window an active
+ Point ls = north.getLocationOnScreen();
+ robot.mouseMove(ls.x + north.getWidth()/2, ls.y + north.getHeight()/2);
+ robot.click();
+
+ // Invoke list
+ ls = south.getLocationOnScreen();
+
+ Point p1 = new Point(
+ (int) (ls.x + south.getWidth() * 0.75),
+ ls.y + south.getHeight() * 3);
+
+ Point p2 = new Point(
+ (int) (ls.x + south.getWidth() * 0.75),
+ ls.y - south.getHeight() * 2);
+
+ Color c1 = robot.getPixelColor(p1.x, p1.y);
+ Color c2 = robot.getPixelColor(p2.x, p2.y);
+
+ int x = ls.x + south.getWidth()/2;
+ int y = ls.y + south.getHeight()/2;
+
+ System.out.println("Trying to click point "+x+", "+y+
+ ", looking for flag to trigger.");
+
+ robot.mouseMove(x, y);
+ robot.waitForIdle(delay);
+ robot.click();
+ robot.waitForIdle(delay);
+
+ if (!southClicked)
+ throw new RuntimeException("Flag is not triggered for point "+x+", "+y+"!");
+
+ robot.waitForIdle();
+
+ Color c1b = robot.getPixelColor(p1.x, p1.y);
+ Color c2b = robot.getPixelColor(p2.x, p2.y);
+
+ if (!c1.equals(c1b) && !south.getBackground().equals(c1b))
+ throw new RuntimeException(
+ "Check for opaque drop down failed at point " + p1 +
+ ". Before click: " + c1 + ", after click: " + c1b +
+ ", expected is " + south.getBackground());
+
+ if (!c2.equals(c2b) && !south.getBackground().equals(c2b))
+ throw new RuntimeException(
+ "Check for opaque drop down failed at point " + p2 +
+ ". Before click: " + c2 + ", after click: " + c2b +
+ ", expected is " + south.getBackground());
+
+ EventQueue.invokeAndWait(this::dispose);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentPerPixelTranslucentGradient.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2010, 2014, 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.*;
+
+/*
+ * @test
+ * @summary Check if a per-pixel translucent and translucent window is dragged
+ * and resized by mouse correctly
+ * Test Description: Check if PERPIXEL_TRANSLUCENT and TRANSLUCENT translucency
+ * types are supported on the current platform. Proceed if they are supported.
+ * Create a window with some components in it, make window undecorated, apply
+ * opacity of 0.7, apply translucent background of 0 and have a gradient
+ * painted as background from fully-transparent to fully-opaque in
+ * componentResized listener. Drag and resize the window using AWT Robot and
+ * verify that translucency is correctly applied with pixels checking. Make
+ * the window appear on top of a known background. Repeat this for specified
+ * JWindow, JDialog, JFrame.
+ * Expected Result: If PERPIXEL_TRANSLUCENT and TRANSLUCENT translucency types
+ * are supported, the window should appear as specified with the translucency.
+ * Both window background and all the controls should be translucent but
+ * background should have a gradient in translucency while controls - not.
+ * @author mrkam
+ * @library ../../../../lib/testlibrary
+ * @build Common ExtendedRobot
+ * @run main TranslucentPerPixelTranslucentGradient
+ */
+
+public class TranslucentPerPixelTranslucentGradient extends Common {
+
+ public static void main(String[] ignored) throws Exception {
+ if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT)
+ && checkTranslucencyMode(GraphicsDevice.WindowTranslucency.TRANSLUCENT))
+ for (Class<Window> windowClass: WINDOWS_TO_TEST)
+ new TranslucentPerPixelTranslucentGradient(windowClass).doTest();
+ }
+
+ public TranslucentPerPixelTranslucentGradient(Class windowClass) throws Exception {
+ super(windowClass, 0.7f, 0f, true);
+ }
+
+ public void doTest() throws Exception {
+ robot.waitForIdle(delay);
+ checkTranslucent();
+ }
+
+ @Override
+ public void applyShape() {
+ gradientWidth = window.getWidth();
+ gradientHeight = window.getHeight();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentWindowClickSwing.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2010, 2014, 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 javax.swing.*;
+import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+/*
+ * @test
+ * @summary Check if swing components present in a window set with opacity less
+ * than 1.0 appears translucent
+ * Test Description: Check if TRANSLUCENT Translucency type is supported for the
+ * current platform. Proceed if supported. Show a window containing some swing
+ * components and set it with opacity less than 1.0. Check if the swing components
+ * appear translucent and check if events trigger correctly for the components
+ * Expected Result: If TRANSLUCENT Translucency type is supported, the components
+ * should appear translucent showing the background. They should trigger events
+ * correctly
+ * @author mrkam
+ * @library ../../../../lib/testlibrary
+ * @build Common ExtendedRobot
+ * @run main TranslucentWindowClickSwing
+ */
+
+public class TranslucentWindowClickSwing extends Common {
+
+ private Component south;
+ private Component center;
+ private Component north;
+
+ public static void main(String[] args) throws Exception{
+ if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.TRANSLUCENT))
+ new TranslucentWindowClickSwing(JWindow.class).doTest();
+ }
+
+ public TranslucentWindowClickSwing(Class windowClass) throws Exception {
+ super(windowClass, 0.2f, 1.0f, false);
+ }
+
+ @Override
+ public void createSwingComponents() {
+ south = new JButton("South");
+ south.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) { clicked |= 1 << 2; }
+ });
+ window.add(south, BorderLayout.SOUTH);
+
+ center = new JList();
+ center.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) { clicked |= 1 << 1; }
+ });
+ window.add(center, BorderLayout.CENTER);
+
+ north = new JTextField("North");
+ north.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) { clicked |= 1 << 0; }
+ });
+ window.add(north, BorderLayout.NORTH);
+ }
+
+ @Override
+ public void doTest() throws Exception {
+ Point ls;
+ robot.waitForIdle();
+
+ ls = north.getLocationOnScreen();
+ checkClick(ls.x + north.getWidth() / 3, ls.y + north.getHeight() / 2, 0);
+
+ ls = center.getLocationOnScreen();
+ checkClick(ls.x + center.getWidth() / 4, ls.y + center.getHeight() / 4, 1);
+
+ ls = center.getLocationOnScreen();
+ checkClick(ls.x + center.getWidth() * 3 / 4, ls.y + center.getHeight() * 3 / 4, 1);
+
+ ls = south.getLocationOnScreen();
+ checkClick(ls.x + south.getWidth() * 2 / 3, ls.y + south.getHeight() / 2, 2);
+
+ EventQueue.invokeAndWait(this::dispose);
+ robot.waitForIdle();
+ }
+}
--- a/jdk/test/lib/testlibrary/jsr292/com/oracle/testlibrary/jsr292/Helper.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/lib/testlibrary/jsr292/com/oracle/testlibrary/jsr292/Helper.java Wed Jul 05 20:01:44 2017 +0200
@@ -52,7 +52,7 @@
public static final long TEST_LIMIT;
static {
String str = System.getProperty("testLimit");
- TEST_LIMIT = str != null ? Long.parseUnsignedLong(str) : 2_000L;
+ TEST_LIMIT = str != null ? Long.parseUnsignedLong(str) : 2000L;
System.out.printf("-DtestLimit=%d%n", TEST_LIMIT);
}
@@ -116,6 +116,48 @@
return size <= lag ? null : calledLog.get(size - lag - 1);
}
+ public static List<Class<?>> randomClasses(Class<?>[] classes, int size) {
+ List<Class<?>> result = new ArrayList<>(size);
+ for (int i = 0; i < size; ++i) {
+ result.add(classes[RNG.nextInt(classes.length)]);
+ }
+ return result;
+ }
+
+ public static List<Class<?>> getParams(List<Class<?>> classes,
+ boolean isVararg, int argsCount) {
+ boolean unmodifiable = true;
+ List<Class<?>> result = classes.subList(0,
+ Math.min(argsCount, (MAX_ARITY / 2) - 1));
+ int extra = 0;
+ if (argsCount >= MAX_ARITY / 2) {
+ result = new ArrayList<>(result);
+ unmodifiable = false;
+ extra = (int) result.stream().filter(Helper::isDoubleCost).count();
+ int i = result.size();
+ while (result.size() + extra < argsCount) {
+ Class<?> aClass = classes.get(i);
+ if (Helper.isDoubleCost(aClass)) {
+ ++extra;
+ if (result.size() + extra >= argsCount) {
+ break;
+ }
+ }
+ result.add(aClass);
+ }
+ }
+ if (isVararg && result.size() > 0) {
+ if (unmodifiable) {
+ result = new ArrayList<>(result);
+ }
+ int last = result.size() - 1;
+ Class<?> aClass = result.get(last);
+ aClass = Array.newInstance(aClass, 2).getClass();
+ result.set(last, aClass);
+ }
+ return result;
+ }
+
public static MethodHandle addTrailingArgs(MethodHandle target, int nargs,
List<Class<?>> classes) {
int targetLen = target.type().parameterCount();
@@ -230,7 +272,7 @@
return randomArgs(params.toArray(new Class<?>[params.size()]));
}
- private static Object castToWrapper(Object value, Class<?> dst) {
+ public static Object castToWrapper(Object value, Class<?> dst) {
Object wrap = null;
if (value instanceof Number) {
wrap = castToWrapperOrNull(((Number) value).longValue(), dst);
@@ -268,7 +310,7 @@
if (dst == byte.class || dst == Byte.class) {
return (byte) (value);
}
- if (dst == boolean.class || dst == boolean.class) {
+ if (dst == boolean.class || dst == Boolean.class) {
return ((value % 29) & 1) == 0;
}
return null;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/java2d/OpenGL/DrawHugeImageTest.java Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014, 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 8040617
+ * @summary Test verifies that an attempt to get an accelerated copy of
+ * a huge buffered image does not result in an OOME.
+ *
+ * @run main DrawHugeImageTest
+ */
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.image.BufferedImage;
+import java.awt.image.VolatileImage;
+
+public class DrawHugeImageTest {
+ // we have to render the BI source several times in order
+ // to get an accelerated copy to be used.
+ static {
+ System.setProperty("sun.java2d.accthreshold", "1");
+ }
+ private static final int max_rendering_count = 5;
+
+ private static final Color srcColor = Color.red;
+ private static final Color dstColor = Color.blue;
+
+ public static void main(String[] args) {
+ BufferedImage src = createSrc();
+
+ VolatileImage dst = createDst();
+ System.out.println("Dst: " + dst);
+ boolean status;
+ int count = max_rendering_count;
+
+ do {
+ System.out.println("render image: " + (max_rendering_count - count));
+ status = render(src, dst);
+
+ } while (status && count-- > 0);
+
+ if (!status || count > 0) {
+ throw new RuntimeException("Test failed: " + count);
+ }
+ }
+
+ private static boolean render(BufferedImage src, VolatileImage dst) {
+ int cnt = 5;
+ do {
+ Graphics2D g = dst.createGraphics();
+ g.setColor(dstColor);
+ g.fillRect(0, 0, dst.getWidth(), dst.getHeight());
+ g.drawImage(src, 0, 0, null);
+ g.dispose();
+ } while (dst.contentsLost() && (--cnt > 0));
+
+ if (cnt == 0) {
+ System.err.println("Test failed: unable to render to volatile destination");
+ return false;
+ }
+
+ BufferedImage s = dst.getSnapshot();
+
+ return s.getRGB(1,1) == srcColor.getRGB();
+ }
+
+ private static BufferedImage createSrc() {
+ final int w = 20000;
+ final int h = 5;
+
+ BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
+ Graphics2D g = img.createGraphics();
+ g.setColor(srcColor);
+ g.fillRect(0, 0, w, h);
+ g.dispose();
+
+ return img;
+ }
+
+ private static VolatileImage createDst() {
+ GraphicsConfiguration gc =
+ GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
+
+ return gc.createCompatibleVolatileImage(200, 200);
+ }
+}
--- a/jdk/test/sun/security/krb5/auto/Context.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/sun/security/krb5/auto/Context.java Wed Jul 05 20:01:44 2017 +0200
@@ -22,15 +22,14 @@
*/
import com.sun.security.auth.module.Krb5LoginModule;
-import java.security.Key;
+
+import java.lang.reflect.Method;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Arrays;
-import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import javax.security.auth.Subject;
-import javax.security.auth.kerberos.KerberosCredMessage;
import javax.security.auth.kerberos.KerberosKey;
import javax.security.auth.kerberos.KerberosTicket;
import javax.security.auth.login.LoginContext;
@@ -41,10 +40,6 @@
import org.ietf.jgss.GSSName;
import org.ietf.jgss.MessageProp;
import org.ietf.jgss.Oid;
-import com.sun.security.jgss.ExtendedGSSContext;
-import com.sun.security.jgss.InquireType;
-import com.sun.security.jgss.AuthorizationDataEntry;
-import com.sun.security.jgss.ExtendedGSSCredential;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.security.Principal;
@@ -78,7 +73,7 @@
public class Context {
private Subject s;
- private ExtendedGSSContext x;
+ private GSSContext x;
private String name;
private GSSCredential cred; // see static method delegated().
@@ -143,7 +138,6 @@
/**
* Logins with username/password as an existing Subject. The
* same subject can be used multiple times to simulate multiple logins.
- * @param s existing subject
*/
public static Context fromUserPass(Subject s,
String user, char[] pass, boolean storeKey) throws Exception {
@@ -222,7 +216,7 @@
@Override
public byte[] run(Context me, byte[] dummy) throws Exception {
GSSManager m = GSSManager.getInstance();
- me.x = (ExtendedGSSContext)m.createContext(
+ me.x = m.createContext(
target.indexOf('@') < 0 ?
m.createName(target, null) :
m.createName(target, GSSName.NT_HOSTBASED_SERVICE),
@@ -267,7 +261,7 @@
asInitiator?
GSSCredential.INITIATE_AND_ACCEPT:
GSSCredential.ACCEPT_ONLY);
- me.x = (ExtendedGSSContext)m.createContext(me.cred);
+ me.x = m.createContext(me.cred);
return null;
}
}, null);
@@ -285,7 +279,7 @@
*
* @return the GSSContext object
*/
- public ExtendedGSSContext x() {
+ public GSSContext x() {
return x;
}
@@ -339,7 +333,7 @@
*/
public void status() throws Exception {
System.out.println("STATUS OF " + name.toUpperCase());
- try {
+ if (x != null) {
StringBuffer sb = new StringBuffer();
if (x.getAnonymityState()) {
sb.append("anon, ");
@@ -362,19 +356,15 @@
if (x.getSequenceDetState()) {
sb.append("seq det, ");
}
- if (x instanceof ExtendedGSSContext) {
- if (((ExtendedGSSContext)x).getDelegPolicyState()) {
- sb.append("deleg policy, ");
- }
+ System.out.println(" Context status of " + name + ": " + sb.toString());
+ if (x.isProtReady() || x.isEstablished()) {
+ System.out.println(" " + x.getSrcName() + " -> " + x.getTargName());
}
- System.out.println("Context status of " + name + ": " + sb.toString());
- System.out.println(x.getSrcName() + " -> " + x.getTargName());
- } catch (Exception e) {
- ;// Don't care
}
+ xstatus();
if (s != null) {
System.out.println("====== START SUBJECT CONTENT =====");
- for (Principal p: s.getPrincipals()) {
+ for (Principal p : s.getPrincipals()) {
System.out.println(" Principal: " + p);
}
for (Object o : s.getPublicCredentials()) {
@@ -405,51 +395,42 @@
}
System.out.println("====== END SUBJECT CONTENT =====");
}
- if (x != null && x instanceof ExtendedGSSContext) {
- if (x.isEstablished()) {
- ExtendedGSSContext ex = (ExtendedGSSContext)x;
- Key k = (Key)ex.inquireSecContext(
- InquireType.KRB5_GET_SESSION_KEY);
- if (k == null) {
- throw new Exception("(Old) Session key cannot be null");
- }
- System.out.println("(Old) Session key is: " + k);
- Key k2 = (Key)ex.inquireSecContext(
- InquireType.KRB5_GET_SESSION_KEY_EX);
- if (k2 == null) {
- throw new Exception("Session key cannot be null");
- }
- System.out.println("Session key is: " + k);
- boolean[] flags = (boolean[])ex.inquireSecContext(
- InquireType.KRB5_GET_TKT_FLAGS);
- if (flags == null) {
- throw new Exception("Ticket flags cannot be null");
+ }
+
+ public void xstatus() throws Exception {
+ System.out.println(" Extended context status:");
+ if (x != null) {
+ try {
+ Class<?> clazz = Class.forName("com.sun.security.jgss.ExtendedGSSContext");
+ if (clazz.isAssignableFrom(x.getClass())) {
+ if (clazz.getMethod("getDelegPolicyState").invoke(x) == Boolean.TRUE) {
+ System.out.println(" deleg policy");
+ }
+ if (x.isEstablished()) {
+ Class<?> inqType = Class.forName("com.sun.security.jgss.InquireType");
+ Method inqMethod = clazz.getMethod("inquireSecContext", inqType);
+ for (Object o : inqType.getEnumConstants()) {
+ System.out.println(" " + o + ":");
+ try {
+ System.out.println(" " + inqMethod.invoke(x, o));
+ } catch (Exception e) {
+ System.out.println(e.getCause());
+ }
+ }
+ }
}
- System.out.println("Ticket flags is: " + Arrays.toString(flags));
- String authTime = (String)ex.inquireSecContext(
- InquireType.KRB5_GET_AUTHTIME);
- if (authTime == null) {
- throw new Exception("Auth time cannot be null");
- }
- System.out.println("AuthTime is: " + authTime);
- if (!x.isInitiator()) {
- AuthorizationDataEntry[] ad = (AuthorizationDataEntry[])ex.inquireSecContext(
- InquireType.KRB5_GET_AUTHZ_DATA);
- System.out.println("AuthzData is: " + Arrays.toString(ad));
+ } catch (ClassNotFoundException cnfe) {
+ System.out.println(" -- ExtendedGSSContext not available");
+ }
+ }
+ if (cred != null) {
+ try {
+ Class<?> clazz2 = Class.forName("com.sun.security.jgss.ExtendedGSSCredential");
+ if (!clazz2.isAssignableFrom(cred.getClass())) {
+ throw new Exception("cred is not extended");
}
- try {
- KerberosCredMessage tok = (KerberosCredMessage)ex.inquireSecContext(
- InquireType.KRB5_GET_KRB_CRED);
- System.out.println("KRB_CRED is " +
- (tok == null?"not ":"") + "available");
- if (tok != null) {
- System.out.println("From " + tok.getSender() + " to "
- + tok.getRecipient());
- System.out.println(Base64.getEncoder().encodeToString(tok.getEncoded()));
- }
- } catch (Exception e) {
- System.out.println("KRB_CRED is not available: " + e);
- }
+ } catch (ClassNotFoundException cnfe) {
+ System.out.println(" -- ExtendedGSSCredential not available");
}
}
}
@@ -591,7 +572,10 @@
if (Context.this.cred == null) {
Context.this.cred = m.createCredential(GSSCredential.INITIATE_ONLY);
}
- return ((ExtendedGSSCredential)Context.this.cred).impersonate(other);
+ return (GSSCredential)
+ Class.forName("com.sun.security.jgss.ExtendedGSSCredential")
+ .getMethod("impersonate", GSSName.class)
+ .invoke(Context.this.cred, other);
}
});
Context out = new Context();
--- a/jdk/test/sun/security/krb5/auto/NewInquireTypes.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/sun/security/krb5/auto/NewInquireTypes.java Wed Jul 05 20:01:44 2017 +0200
@@ -29,6 +29,7 @@
* @run main/othervm NewInquireTypes
*/
+import com.sun.security.jgss.ExtendedGSSContext;
import com.sun.security.jgss.InquireType;
import sun.security.jgss.GSSUtil;
import sun.security.krb5.internal.KRBCred;
@@ -52,10 +53,12 @@
Context.handshake(c, s);
+ ExtendedGSSContext ctxt = (ExtendedGSSContext)c.x();
EncryptionKey key = (EncryptionKey)
- c.x().inquireSecContext(InquireType.KRB5_GET_SESSION_KEY_EX);
+ ctxt.inquireSecContext(InquireType.KRB5_GET_SESSION_KEY_EX);
KerberosCredMessage cred = (KerberosCredMessage)
- c.x().inquireSecContext(InquireType.KRB5_GET_KRB_CRED);
+ ctxt.inquireSecContext(InquireType.KRB5_GET_KRB_CRED);
+ c.status();
// Confirm the KRB_CRED message is encrypted with the session key.
new KRBCred(cred.getEncoded()).encPart.decrypt(
--- a/jdk/test/sun/security/krb5/auto/OkAsDelegate.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/sun/security/krb5/auto/OkAsDelegate.java Wed Jul 05 20:01:44 2017 +0200
@@ -48,6 +48,7 @@
* @summary Support OK-AS-DELEGATE flag
*/
import com.sun.security.jgss.ExtendedGSSContext;
+import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.Oid;
@@ -102,7 +103,7 @@
cx.requestCredDeleg(requestDelegState);
cx.requestDelegPolicy(requestDelegPolicyState);
s.startAsServer(mech);
- ExtendedGSSContext sx = (ExtendedGSSContext)s.x();
+ GSSContext sx = s.x();
Context.handshake(c, s);
--- a/jdk/test/sun/security/krb5/auto/OkAsDelegateXRealm.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/sun/security/krb5/auto/OkAsDelegateXRealm.java Wed Jul 05 20:01:44 2017 +0200
@@ -42,6 +42,8 @@
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
+
+import com.sun.security.jgss.ExtendedGSSContext;
import org.ietf.jgss.GSSException;
import sun.security.jgss.GSSUtil;
import sun.security.krb5.Config;
@@ -129,7 +131,7 @@
for (int i=0; i<2; i++) {
c.startAsClient("host@host.r3.local", GSSUtil.GSS_KRB5_MECH_OID);
s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
- c.x().requestDelegPolicy(true);
+ ((ExtendedGSSContext)c.x()).requestDelegPolicy(true);
Context.handshake(c, s);
boolean succeed = true;
--- a/jdk/test/sun/security/krb5/auto/SSL.java Thu Sep 18 13:27:06 2014 -0700
+++ b/jdk/test/sun/security/krb5/auto/SSL.java Wed Jul 05 20:01:44 2017 +0200
@@ -186,13 +186,13 @@
// Client checks "initiate", then server gets the name
// and checks "accept". Second connection resume.
if (!permChecks.equals("IA")) {
- throw new Exception();
+ throw new Exception(permChecks);
}
} else {
// For bound, JAAS checks "accept" once. Server checks again,
// client then checks "initiate". Second connection resume.
if (!permChecks.equals("AAI")) {
- throw new Exception();
+ throw new Exception(permChecks);
}
}
}
--- a/make/HotspotWrapper.gmk Thu Sep 18 13:27:06 2014 -0700
+++ b/make/HotspotWrapper.gmk Wed Jul 05 20:01:44 2017 +0200
@@ -42,7 +42,7 @@
# not doing it breaks builds on msys.
$(HOTSPOT_OUTPUTDIR)/_hotspot.timestamp: $(HOTSPOT_FILES)
@$(MKDIR) -p $(HOTSPOT_OUTPUTDIR)
- @($(CD) $(HOTSPOT_TOPDIR)/make && $(MAKE) -j1 $(HOTSPOT_MAKE_ARGS) SPEC=$(HOTSPOT_SPEC) BASE_SPEC=$(BASE_SPEC))
+ @($(CD) $(HOTSPOT_TOPDIR)/make && $(MAKE) $(HOTSPOT_MAKE_ARGS) SPEC=$(HOTSPOT_SPEC) BASE_SPEC=$(BASE_SPEC))
$(TOUCH) $@
hotspot: $(HOTSPOT_OUTPUTDIR)/_hotspot.timestamp
--- a/make/Main.gmk Thu Sep 18 13:27:06 2014 -0700
+++ b/make/Main.gmk Wed Jul 05 20:01:44 2017 +0200
@@ -298,7 +298,9 @@
# Verification targets
verify-modules:
+ @$(call TargetEnter)
+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f CheckModules.gmk)
+ @$(call TargetExit)
ALL_TARGETS += verify-modules
@@ -400,7 +402,7 @@
main-jars: java.security.jgss-libs
endif
- images: jars demos samples exploded-image source-tips
+ images: jars demos samples exploded-image verify-modules source-tips
bootcycle-images: images
@@ -476,7 +478,7 @@
################################################################################
-all: images docs verify-modules
+all: images docs
default: exploded-image
ALL_TARGETS += default all
@@ -491,7 +493,7 @@
# file.
CLEAN_COMPONENTS += langtools corba hotspot jdk nashorn images \
- bootcycle-build docs docstemp test
+ bootcycle-build docs docstemp test make-support
CLEAN_TARGETS := $(addprefix clean-, $(CLEAN_COMPONENTS))
# Remove everything, except the output from configure.
--- a/make/common/Modules.gmk Thu Sep 18 13:27:06 2014 -0700
+++ b/make/common/Modules.gmk Wed Jul 05 20:01:44 2017 +0200
@@ -26,6 +26,9 @@
ifndef _MODULES_GMK
_MODULES_GMK := 1
+include JavaCompilation.gmk
+include SetupJavaCompilers.gmk
+
################################################################################
# Module list macros
@@ -50,8 +53,32 @@
$(patsubst %,%/*/$(OPENJDK_TARGET_OS)/classes/*, $(ALL_TOP_SRC_DIRS))))))))))))
endef
-MODULES_LIST_FILE := $(SRC_ROOT)/make/common/modules.list
-MODULE_DEPS_MAKEFILE := $(OUTPUT_ROOT)/module-deps.gmk
+# Find all modules with source for the target platform.
+define FindAllModules
+ $(sort $(filter-out closed demo sample, $(notdir $(patsubst %/,%, $(dir \
+ $(wildcard $(patsubst %, %/*/share, $(ALL_TOP_SRC_DIRS)) \
+ $(patsubst %, %/*/$(OPENJDK_TARGET_OS), $(ALL_TOP_SRC_DIRS)) \
+ $(patsubst %, %/*/$(OPENJDK_TARGET_OS_API_DIR), $(ALL_TOP_SRC_DIRS))))))))
+endef
+
+################################################################################
+
+$(eval $(call SetupJavaCompilation,BUILD_GENMODULESLIST, \
+ SETUP := BOOT_JAVAC, \
+ SRC := $(JDK_TOPDIR)/make/src/classes, \
+ INCLUDES := build/tools/module, \
+ BIN := $(MAKESUPPORT_OUTPUTDIR)/bt_classes_moduleslist))
+
+TOOL_GENMODULESLIST = $(JAVA_SMALL) \
+ -cp "$(MAKESUPPORT_OUTPUTDIR)/bt_classes_moduleslist" \
+ build.tools.module.GenModulesList
+
+MODULES_LIST_FILE := $(MAKESUPPORT_OUTPUTDIR)/modules.list
+MODULE_DEPS_MAKEFILE := $(MAKESUPPORT_OUTPUTDIR)/module-deps.gmk
+
+$(MODULES_LIST_FILE): $(SRC_ROOT)/modules.xml \
+ $(BUILD_GENMODULESLIST)
+ $(TOOL_GENMODULESLIST) -o $@ $(filter %.xml, $^)
$(MODULE_DEPS_MAKEFILE): $(MODULES_LIST_FILE)
$(CAT) $^ | $(SED) -e 's/^\([^:]*\):/DEPS_\1 :=/g' > $@
@@ -63,14 +90,6 @@
$(DEPS_$(strip $1))
endef
-# Find all modules with source for the target platform.
-define FindAllModules
- $(sort $(filter-out closed demo sample, $(notdir $(patsubst %/,%, $(dir \
- $(wildcard $(patsubst %, %/*/share, $(ALL_TOP_SRC_DIRS)) \
- $(patsubst %, %/*/$(OPENJDK_TARGET_OS), $(ALL_TOP_SRC_DIRS)) \
- $(patsubst %, %/*/$(OPENJDK_TARGET_OS_API_DIR), $(ALL_TOP_SRC_DIRS))))))))
-endef
-
################################################################################
# Hook to include the corresponding custom file, if present.
--- a/make/common/SetupJavaCompilers.gmk Thu Sep 18 13:27:06 2014 -0700
+++ b/make/common/SetupJavaCompilers.gmk Wed Jul 05 20:01:44 2017 +0200
@@ -34,6 +34,12 @@
# make JAVAC_WARNINGS="-Xlint:all -Xmaxwarns 10000"
JAVAC_WARNINGS := -Xlint:all,-deprecation -Werror
+# The BOOT_JAVAC setup uses the boot jdk compiler to compile the tools
+# and the interim javac, to be run by the boot jdk.
+$(eval $(call SetupJavaCompiler,BOOT_JAVAC, \
+ JAVAC := $(JAVAC), \
+ FLAGS := -XDignore.symbol.file=true -g -Xlint:all$(COMMA)-deprecation -Werror))
+
# Any java code executed during a JDK build to build other parts of the JDK must be
# executed by the bootstrap JDK (probably with -Xbootclasspath/p: ) and for this
# purpose must be built with -target PREVIOUS for bootstrapping purposes, which
--- a/make/common/modules.list Thu Sep 18 13:27:06 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-java.base:
-java.logging: java.base
-java.security.sasl: java.logging java.base
-java.naming: java.security.sasl java.base
-java.security.acl: java.base
-jdk.charsets: java.base
-java.scripting: java.base
-java.xml: java.base
-java.sql: java.xml java.logging java.base
-jdk.scripting.nashorn: java.scripting java.logging java.base
-java.rmi: java.logging java.base
-java.prefs: java.xml java.base
-java.desktop: jdk.charsets java.prefs java.xml java.logging java.base
-java.corba: java.naming java.rmi java.desktop java.logging java.base
-java.compiler: java.logging java.base
-jdk.compiler: java.compiler java.base
-jdk.javadoc: java.compiler java.xml jdk.compiler java.base
-jdk.rmic: java.corba jdk.compiler jdk.javadoc java.base
-jdk.jvmstat: java.rmi java.base
-jdk.attach: jdk.jvmstat java.base
-jdk.jcmd: jdk.jvmstat jdk.attach java.base
-jdk.jdi: jdk.attach java.base
-jdk.hotspot.agent: java.rmi java.scripting java.desktop java.base jdk.jdi
-jdk.hprof.agent: java.base
-java.management: java.naming java.rmi java.logging java.base
-jdk.jconsole: java.management jdk.jvmstat java.rmi jdk.attach java.desktop java.logging java.base
-java.activation: java.desktop java.logging java.base
-java.xml.bind: java.activation java.compiler java.xml java.desktop java.logging java.base
-jdk.xml.bind: java.activation java.compiler java.xml.bind java.xml java.desktop java.logging jdk.compiler java.base
-jdk.httpserver: java.logging java.base
-java.annotations.common: java.base
-java.xml.soap: java.activation java.xml.bind java.xml java.desktop java.logging java.base
-java.xml.ws: java.activation java.management jdk.httpserver java.rmi java.annotations.common java.xml.bind java.xml java.desktop java.logging java.xml.soap java.base
-jdk.xml.ws: jdk.xml.bind java.compiler java.rmi java.xml.ws java.xml.bind java.xml java.logging java.base
-java.sql.rowset: java.naming java.sql java.xml java.logging java.base
-java.instrument: java.base
-java.security.jgss: java.naming java.security.sasl java.logging java.base
-java.xml.crypto: java.xml java.logging java.base
-jdk.localedata: java.base
-jdk.crypto.ec: java.base
-jdk.crypto.pkcs11: jdk.crypto.ec java.base
-jdk.crypto.mscapi: java.base
-jdk.naming.rmi: java.naming java.rmi java.base
-jdk.zipfs: java.base
-jdk.naming.dns: java.naming java.base
-java.smartcardio: java.base
-jdk.dev: jdk.xml.bind jdk.xml.ws java.scripting jdk.rmic java.xml jdk.compiler java.base
-jdk.snmp: java.management java.security.acl java.logging java.base
-jdk.jdwp.agent: java.base
-jdk.security.auth: java.naming java.security.jgss java.base
-jdk.sctp: java.base
-jdk.runtime: java.desktop java.base
-jdk.jfr: java.management java.xml java.base
-jdk.deploy.osx: java.scripting java.desktop java.base
--- a/modules.xml Thu Sep 18 13:27:06 2014 -0700
+++ b/modules.xml Wed Jul 05 20:01:44 2017 +0200
@@ -243,6 +243,7 @@
<to>java.rmi</to>
<to>java.security.jgss</to>
<to>java.security.sasl</to>
+ <to>java.sql</to>
<to>jdk.charsets</to>
<to>jdk.deploy.osx</to>
<to>jdk.dev</to>
@@ -250,6 +251,7 @@
<to>jdk.jvmstat</to>
<to>jdk.runtime</to>
<to>jdk.security.auth</to>
+ <to>jdk.security.jgss</to>
</export>
<export>
<name>sun.net.dns</name>
@@ -326,6 +328,7 @@
</export>
<export>
<name>sun.security.internal.spec</name>
+ <to>jdk.crypto.mscapi</to>
<to>jdk.crypto.pkcs11</to>
<to>jdk.crypto.ucrypto</to>
</export>
@@ -730,6 +733,10 @@
<export>
<name>javax.swing.undo</name>
</export>
+ <export>
+ <name>sun.awt</name>
+ <to>oracle.accessbridge</to>
+ </export>
</module>
<module>
<name>java.instrument</name>
@@ -900,12 +907,7 @@
<module>
<name>java.security.jgss</name>
<depend>java.base</depend>
- <depend>java.logging</depend>
<depend>java.naming</depend>
- <depend>java.security.sasl</depend>
- <export>
- <name>com.sun.security.jgss</name>
- </export>
<export>
<name>javax.security.auth.kerberos</name>
</export>
@@ -924,6 +926,14 @@
<name>sun.security.krb5.internal.ktab</name>
<to>jdk.security.auth</to>
</export>
+ <export>
+ <name>sun.security.jgss</name>
+ <to>jdk.security.jgss</to>
+ </export>
+ <export>
+ <name>sun.security.krb5.internal</name>
+ <to>jdk.security.jgss</to>
+ </export>
</module>
<module>
<name>java.security.sasl</name>
@@ -934,7 +944,7 @@
</export>
<export>
<name>com.sun.security.sasl.util</name>
- <to>java.security.jgss</to>
+ <to>jdk.security.jgss</to>
</export>
</module>
<module>
@@ -1570,6 +1580,10 @@
</export>
</module>
<module>
+ <name>jdk.crypto.mscapi</name>
+ <depend>java.base</depend>
+ </module>
+ <module>
<name>jdk.crypto.pkcs11</name>
<depend>java.base</depend>
<depend>jdk.crypto.ec</depend>
@@ -1752,6 +1766,16 @@
</export>
</module>
<module>
+ <name>jdk.security.jgss</name>
+ <depend>java.base</depend>
+ <depend>java.logging</depend>
+ <depend re-exports="true">java.security.jgss</depend>
+ <depend>java.security.sasl</depend>
+ <export>
+ <name>com.sun.security.jgss</name>
+ </export>
+ </module>
+ <module>
<name>jdk.xml.bind</name>
<depend>java.activation</depend>
<depend>java.base</depend>
--- a/nashorn/.hgtags Thu Sep 18 13:27:06 2014 -0700
+++ b/nashorn/.hgtags Wed Jul 05 20:01:44 2017 +0200
@@ -264,3 +264,4 @@
00c31e5eaf26f9b238165157b9d1c617b03abcb6 jdk9-b28
e541ebaf2ab7038333ad0c13f4decd327c26dd15 jdk9-b29
072dbed6c5d968a6b9e156c36cd8838b4ff86ea1 jdk9-b30
+77efdecfa2a5c28672b7c7dcc2d1b52dcb90d493 jdk9-b31
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FieldObjectCreator.java Thu Sep 18 13:27:06 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FieldObjectCreator.java Wed Jul 05 20:01:44 2017 +0200
@@ -231,7 +231,7 @@
if (symbol != null) {
if (hasArguments() && symbol.isParam()) {
symbol.setFieldIndex(paramCount++);
- } else {
+ } else if (!isValidArrayIndex(getArrayIndex(tuple.key))) {
symbol.setFieldIndex(fieldCount++);
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Thu Sep 18 13:27:06 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Wed Jul 05 20:01:44 2017 +0200
@@ -439,8 +439,8 @@
// current ScriptContext to use - can be null.
private ScriptContext scontext;
- // associated Property object for "context" property.
- private jdk.nashorn.internal.runtime.Property scontextProperty;
+ // current ScriptEngine associated - can be null.
+ private ScriptEngine engine;
/**
* Set the current script context
@@ -448,7 +448,6 @@
*/
public void setScriptContext(final ScriptContext scontext) {
this.scontext = scontext;
- scontextProperty.setValue(this, this, scontext, false);
}
// global constants for this global - they can be replaced with MethodHandle.constant until invalidated
@@ -581,6 +580,7 @@
return;
}
+ this.engine = engine;
init(engine);
}
@@ -917,6 +917,13 @@
}
}
+ switch (nameStr) {
+ case "context":
+ return sctxt;
+ case "engine":
+ return global.engine;
+ }
+
if (self == UNDEFINED) {
// scope access and so throw ReferenceError
throw referenceError(global, "not.defined", nameStr);
@@ -1789,9 +1796,6 @@
}
if (engine != null) {
- final int NOT_ENUMERABLE_NOT_CONFIG = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE;
- scontextProperty = addOwnProperty("context", NOT_ENUMERABLE_NOT_CONFIG, null);
- addOwnProperty("engine", NOT_ENUMERABLE_NOT_CONFIG, engine);
// default file name
addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
// __noSuchProperty__ hook for ScriptContext search of missing variables
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Thu Sep 18 13:27:06 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Wed Jul 05 20:01:44 2017 +0200
@@ -54,6 +54,7 @@
import static jdk.nashorn.internal.parser.TokenType.TERNARY;
import static jdk.nashorn.internal.parser.TokenType.WHILE;
+import java.io.Serializable;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
@@ -2977,11 +2978,13 @@
* Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer
* for resuming parsing after skipping a function body.
*/
- private static class ParserState {
+ private static class ParserState implements Serializable {
private final int position;
private final int line;
private final int linePosition;
+ private static final long serialVersionUID = -2382565130754093694L;
+
ParserState(final int position, final int line, final int linePosition) {
this.position = position;
this.line = line;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AccessorProperty.java Thu Sep 18 13:27:06 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AccessorProperty.java Wed Jul 05 20:01:44 2017 +0200
@@ -119,7 +119,7 @@
* produce different boun method handles wrapping the same access mechanism
* depending on callsite
*/
- private MethodHandle[] GETTER_CACHE = new MethodHandle[NOOF_TYPES];
+ private transient MethodHandle[] GETTER_CACHE = new MethodHandle[NOOF_TYPES];
/**
* Create a new accessor property. Factory method used by nasgen generated code.
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java Thu Sep 18 13:27:06 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java Wed Jul 05 20:01:44 2017 +0200
@@ -101,7 +101,7 @@
private final int slot;
/** SwitchPoint that is invalidated when property is changed, optional */
- protected SwitchPoint changeCallback;
+ protected transient SwitchPoint changeCallback;
private static final long serialVersionUID = 2099814273074501176L;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java Thu Sep 18 13:27:06 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java Wed Jul 05 20:01:44 2017 +0200
@@ -568,9 +568,7 @@
for (final Property property : otherProperties) {
// This method is only safe to use with non-slotted, native getter/setter properties
assert property.getSlot() == -1;
- if (isValidArrayIndex(getArrayIndex(property.getKey()))) {
- newMap.setContainsArrayKeys();
- }
+ assert !(isValidArrayIndex(getArrayIndex(property.getKey())));
}
return newMap;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Thu Sep 18 13:27:06 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Wed Jul 05 20:01:44 2017 +0200
@@ -125,6 +125,15 @@
@Override
public Comparison compareConversion(final Class<?> sourceType, final Class<?> targetType1, final Class<?> targetType2) {
+ if (sourceType == ConsString.class) {
+ if (String.class == targetType1 || CharSequence.class == targetType1) {
+ return Comparison.TYPE_1_BETTER;
+ }
+
+ if (String.class == targetType2 || CharSequence.class == targetType2) {
+ return Comparison.TYPE_2_BETTER;
+ }
+ }
return linkerServices.compareConversion(sourceType, targetType1, targetType2);
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java Thu Sep 18 13:27:06 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java Wed Jul 05 20:01:44 2017 +0200
@@ -131,11 +131,16 @@
}
return getInvocation(EMPTY_ELEM_GETTER, self, linkerServices, desc);
case "setProp":
- case "setElem":
+ case "setElem": {
+ final boolean strict = NashornCallSiteDescriptor.isStrict(desc);
+ if (strict) {
+ throw typeError("cant.set.property", getArgument(linkRequest), ScriptRuntime.safeToString(self));
+ }
if (desc.getOperand() != null) {
return getInvocation(EMPTY_PROP_SETTER, self, linkerServices, desc);
}
return getInvocation(EMPTY_ELEM_SETTER, self, linkerServices, desc);
+ }
default:
break;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties Thu Sep 18 13:27:06 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties Wed Jul 05 20:01:44 2017 +0200
@@ -92,7 +92,7 @@
# other wrong usages of property
type.error.property.has.no.setter=Cannot set property "{0}" of {1} that has only a getter
-type.error.cant.set.proto.to.non.object=Cannot set Object {0}'s __proto__ to be a non-object like {1}
+type.error.cant.set.proto.to.non.object=Cannot set Object {0}''s __proto__ to be a non-object like {1}
type.error.no.such.function={1} has no such function "{0}"
type.error.no.such.java.class=No such Java class: {0}
type.error.no.such.java.constructor=No such Java constructor: {0}
@@ -125,10 +125,10 @@
type.error.cant.load.script=Cannot load script from {0}
type.error.JSON.stringify.cyclic=JSON.stringify got a cyclic data structure
type.error.cant.convert.string.to.char=Cannot convert string to character; its length must be exactly 1
-type.error.cant.convert.number.to.char=Cannot convert number to character; it's out of 0-65535 range
+type.error.cant.convert.number.to.char=Cannot convert number to character; it is out of 0-65535 range
type.error.cant.convert.to.java.string=Cannot convert object of type {0} to a Java argument of string type
type.error.cant.convert.to.java.number=Cannot convert object of type {0} to a Java argument of number type
-type.error.cant.convert.to.javascript.array=Can only convert Java arrays and lists to JavaScript arrays. Can't convert object of type {0}.
+type.error.cant.convert.to.javascript.array=Can only convert Java arrays and lists to JavaScript arrays. Cannot convert object of type {0}.
type.error.extend.expects.at.least.one.argument=Java.extend needs at least one argument.
type.error.extend.expects.at.least.one.type.argument=Java.extend needs at least one type argument.
type.error.extend.expects.java.types=Java.extend needs Java types as its arguments.
@@ -141,10 +141,10 @@
type.error.extend.ERROR_FINAL_FINALIZER=Can not extend class because {0} has a final finalize method.
type.error.no.constructor.matches.args=Can not construct {0} with the passed arguments; they do not match any of its constructor signatures.
type.error.no.method.matches.args=Can not invoke method {0} with the passed arguments; they do not match any of its method signatures.
-type.error.method.not.constructor=Java method {0} can't be used as a constructor.
+type.error.method.not.constructor=Java method {0} cannot be used as a constructor.
type.error.env.not.object=$ENV must be an Object.
type.error.unsupported.java.to.type=Unsupported Java.to target type {0}.
-type.error.constructor.requires.new=Constructor {0} requires 'new'.
+type.error.constructor.requires.new=Constructor {0} requires "new".
type.error.new.on.nonpublic.javatype=new cannot be used with non-public java type {0}.
range.error.dataview.constructor.offset=Wrong offset or length in DataView constructor
--- a/nashorn/test/script/basic/JDK-8043232.js Thu Sep 18 13:27:06 2014 -0700
+++ b/nashorn/test/script/basic/JDK-8043232.js Wed Jul 05 20:01:44 2017 +0200
@@ -29,14 +29,14 @@
*/
// call explicit constructor
-print(new (java.awt["Color(int,int,int)"])(255,0,255));
+print(new (java.lang["String(char[],int,int)"])(['a','b', 'c', 'd'], 1, 3));
// print the constructor itself
-print(java.awt["Color(int,int,int)"]);
+print(java.lang["String(char[],int,int)"]);
// store constructor to call later
-var Color = java.awt["Color(int,int,int)"];
+var Color = java.lang["String(char[],int,int)"];
// call stored constructor
-print(new Color(33, 233, 2))
+print(new Color(['r','r', 'e', 'd'], 1, 3))
// check if default constructor works
var obj = new (java.lang["Object()"])();
--- a/nashorn/test/script/basic/JDK-8043232.js.EXPECTED Thu Sep 18 13:27:06 2014 -0700
+++ b/nashorn/test/script/basic/JDK-8043232.js.EXPECTED Wed Jul 05 20:01:44 2017 +0200
@@ -1,14 +1,14 @@
-java.awt.Color[r=255,g=0,b=255]
-[jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)]
-java.awt.Color[r=33,g=233,b=2]
+bcd
+[jdk.internal.dynalink.beans.SimpleDynamicMethod String java.lang.String.java.lang.String(char[],int,int)]
+red
TypeError: No such Java class: java.lang.NonExistent
TypeError: No such Java constructor: Object(String)
TypeError: Java constructor signature invalid: Object()xxxxx
TypeError: Java constructor signature invalid: Object(
TypeError: Java constructor signature invalid: Object)
-TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.lang.System.getProperty] cant be used as a constructor.
-TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.io.PrintStream.println] cant be used as a constructor.
-TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)] requires new.
+TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.lang.System.getProperty] cannot be used as a constructor.
+TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.io.PrintStream.println] cannot be used as a constructor.
+TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod String java.lang.String.java.lang.String(char[],int,int)] requires "new".
TypeError: No such Java constructor: Runnable()
TypeError: No such Java constructor: Runnable(int)
java.lang.InstantiationException: java.io.InputStream
--- a/nashorn/test/script/basic/JDK-8049086.js Thu Sep 18 13:27:06 2014 -0700
+++ b/nashorn/test/script/basic/JDK-8049086.js Wed Jul 05 20:01:44 2017 +0200
@@ -58,7 +58,7 @@
// (a) Java methods (b) Java classes (as these respond to new)
// (c) FunctionalInterface objects (d) JSObjects that are 'functions'
-print("java.awt.Color is java function? " + Java.isJavaFunction(java.awt.Color));
+print("java.lang.String is java function? " + Java.isJavaFunction(java.lang.String));
print("java.lang.Runnable instance is java function? "
+ Java.isJavaFunction(new java.lang.Runnable(function() {})));
print("eval is java function? " + Java.isJavaFunction(eval));
--- a/nashorn/test/script/basic/JDK-8049086.js.EXPECTED Thu Sep 18 13:27:06 2014 -0700
+++ b/nashorn/test/script/basic/JDK-8049086.js.EXPECTED Wed Jul 05 20:01:44 2017 +0200
@@ -13,7 +13,7 @@
Object is script object? true
{} is script object? true
/foo/ is script object? true
-java.awt.Color is java function? true
+java.lang.String is java function? true
java.lang.Runnable instance is java function? true
eval is java function? false
println is java function? true
--- a/nashorn/test/script/basic/JDK-8049242.js Thu Sep 18 13:27:06 2014 -0700
+++ b/nashorn/test/script/basic/JDK-8049242.js Wed Jul 05 20:01:44 2017 +0200
@@ -29,14 +29,14 @@
*/
// call explicit constructor
-print(new (Java.type("java.awt.Color")["(int,int,int)"])(255,0,255));
+print(new (Java.type("java.lang.String")["(char[],int,int)"])(['a', 'b', 'c'],0, 3));
// print the constructor itself
-print(Java.type("java.awt.Color")["(int,int,int)"]);
+print(Java.type("java.lang.String")["(char[],int,int)"]);
// store constructor to call later
-var Color = Java.type("java.awt.Color")["(int,int,int)"];
+var Color = Java.type("java.lang.String")["(char[],int,int)"];
// call stored constructor
-print(new Color(33, 233, 2))
+print(new Color(['j', 'a', 'v', 'a'], 1, 3))
// check if default constructor works
var obj = new (Java.type("java.lang.Object")["()"])();
--- a/nashorn/test/script/basic/JDK-8049242.js.EXPECTED Thu Sep 18 13:27:06 2014 -0700
+++ b/nashorn/test/script/basic/JDK-8049242.js.EXPECTED Wed Jul 05 20:01:44 2017 +0200
@@ -1,10 +1,10 @@
-java.awt.Color[r=255,g=0,b=255]
-[jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)]
-java.awt.Color[r=33,g=233,b=2]
+abc
+[jdk.internal.dynalink.beans.SimpleDynamicMethod String java.lang.String.java.lang.String(char[],int,int)]
+ava
TypeError: null is not a function
TypeError: null is not a function
TypeError: null is not a function
-TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)] requires new.
+TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod String java.lang.String.java.lang.String(char[],int,int)] requires "new".
TypeError: null is not a function
TypeError: null is not a function
java.lang.InstantiationException: java.io.InputStream
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8056978.js Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/**
+ * JDK-8056978: ClassCastException: cannot cast jdk.nashorn.internal.scripts.JO*
+ *
+ * @test
+ * @run
+ */
+
+var obj1 = {
+ 'name': 'test name',
+ '1': '1',
+ '2': '2',
+ '3': '3',
+ '4': '4',
+ '5': '5'
+};
+
+var obj2 = {
+ 'name': 'hello'
+};
+
+print(obj2['name']);
+print(obj2.name);
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8056978.js.EXPECTED Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,2 @@
+hello
+hello
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8058422.js Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/**
+ * JDK-8058422: Users should be able to overwrite "context" and "engine" variables
+ *
+ * @test
+ * @run
+ */
+
+var m = new javax.script.ScriptEngineManager();
+var e = m.getEngineByName("nashorn");
+e.put("foo", "hello");
+var obj = e.eval("context.getAttribute('foo')");
+if (obj != "hello") {
+ fail("Expected 'obj' to be 'hello'");
+}
+
+e.put("context", "bar");
+if (e.eval("context") != "bar") {
+ fail("Expected 'context' to be 'bar'");
+}
+
+if (e.eval("foo") != "hello") {
+ fail("Expected 'foo' to be 'hello'");
+}
+
+if (e.eval("engine") != e) {
+ fail("'engine' is not evaluaed to current engine");
+}
+
+e.put("engine", "foobar");
+if (e.eval("engine") != "foobar") {
+ fail("'engine' is not evalued to 'foobar'");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8058545.js Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/**
+ * JDK-8058545: With strict mode, bean property assignment of a non-existent property should result in TypeError
+ *
+ * @test
+ * @run
+ */
+
+'use strict';
+var File = Java.type("java.io.File");
+var f = new File(".");
+try {
+ f.foo = 33;
+ fail("Should have thrown TypeError");
+} catch (e) {
+ if (! (e instanceof TypeError)) {
+ fail("Expected TypeError, got " + e);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8058615.js Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/**
+ * JDK-8058615: Overload resolution ambiguity involving ConsString
+ *
+ * @test
+ * @run
+ */
+
+var strw = new java.io.StringWriter();
+var bufw = new java.io.BufferedWriter(strw);
+var s = "hello ";
+bufw.write(s + "world");
+bufw.close();
+print(strw.toString());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8058615.js.EXPECTED Wed Jul 05 20:01:44 2017 +0200
@@ -0,0 +1,1 @@
+hello world
--- a/nashorn/test/src/jdk/nashorn/api/scripting/ScopeTest.java Thu Sep 18 13:27:06 2014 -0700
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScopeTest.java Wed Jul 05 20:01:44 2017 +0200
@@ -582,6 +582,60 @@
assertEquals(e.eval("x", newCtxt), 2);
}
+ // @bug 8058422: Users should be able to overwrite "context" and "engine" variables
+ @Test
+ public static void contextOverwriteTest() throws ScriptException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = new SimpleBindings();
+ b.put("context", "hello");
+ b.put("foo", 32);
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+ e.setContext(newCtxt);
+ assertEquals(e.eval("context"), "hello");
+ assertEquals(((Number)e.eval("foo")).intValue(), 32);
+ }
+
+ // @bug 8058422: Users should be able to overwrite "context" and "engine" variables
+ @Test
+ public static void contextOverwriteInScriptTest() throws ScriptException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ e.put("foo", 32);
+
+ assertEquals(((Number)e.eval("foo")).intValue(), 32);
+ assertEquals(e.eval("context = 'bar'"), "bar");
+ assertEquals(((Number)e.eval("foo")).intValue(), 32);
+ }
+
+ // @bug 8058422: Users should be able to overwrite "context" and "engine" variables
+ @Test
+ public static void engineOverwriteTest() throws ScriptException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = new SimpleBindings();
+ b.put("engine", "hello");
+ b.put("foo", 32);
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+ e.setContext(newCtxt);
+ assertEquals(e.eval("engine"), "hello");
+ assertEquals(((Number)e.eval("foo")).intValue(), 32);
+ }
+
+ // @bug 8058422: Users should be able to overwrite "context" and "engine" variables
+ @Test
+ public static void engineOverwriteInScriptTest() throws ScriptException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ e.put("foo", 32);
+
+ assertEquals(((Number)e.eval("foo")).intValue(), 32);
+ assertEquals(e.eval("engine = 'bar'"), "bar");
+ assertEquals(((Number)e.eval("foo")).intValue(), 32);
+ }
+
// @bug 8044750: megamorphic getter for scope objects does not call __noSuchProperty__ hook
@Test
public static void testMegamorphicGetInGlobal() throws Exception {