diff --git a/make/CompileCommands.gmk b/make/CompileCommands.gmk index ad729830e53..494bbd1d3f1 100644 --- a/make/CompileCommands.gmk +++ b/make/CompileCommands.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -45,11 +45,6 @@ $(OUTPUTDIR)/compile_commands.json: $(wildcard $(MAKESUPPORT_OUTPUTDIR)/compile- $(RM) $@ $(FIND) $(MAKESUPPORT_OUTPUTDIR)/compile-commands/ -name \*.json | \ $(SORT) | $(XARGS) $(CAT) >> $@.tmp - $(if $(FIXPATH),$(FIXPATH) $(AWK) 'BEGIN { \ - tmpfile = substr(ARGV[2],2); \ - cmd = "$(CP) " "\047" tmpfile "\047" " $@.tmp"; \ - system(cmd); \ - }' -- @$@.tmp) $(SED) -e '1s/^/[\$(NEWLINE)/' -e '$(DOLLAR)s/,\s\{0,\}$(DOLLAR)/\$(NEWLINE)]/' $@.tmp > $@ $(RM) $@.tmp diff --git a/make/RunTestsPrebuiltSpec.gmk b/make/RunTestsPrebuiltSpec.gmk index 30cb6d85946..a12a5383c6b 100644 --- a/make/RunTestsPrebuiltSpec.gmk +++ b/make/RunTestsPrebuiltSpec.gmk @@ -153,7 +153,6 @@ LN := ln MIG := mig MKDIR := mkdir MV := mv -NAWK := nawk NICE := nice PATCH := patch PRINTF := printf diff --git a/make/autoconf/basic_tools.m4 b/make/autoconf/basic_tools.m4 index 9f0eea42d84..dd1cd3935c4 100644 --- a/make/autoconf/basic_tools.m4 +++ b/make/autoconf/basic_tools.m4 @@ -57,7 +57,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS], UTIL_REQUIRE_PROGS(MKDIR, [gmkdir mkdir]) UTIL_REQUIRE_PROGS(MKTEMP, mktemp) UTIL_REQUIRE_PROGS(MV, mv) - UTIL_REQUIRE_PROGS(NAWK, [nawk gawk awk]) + UTIL_REQUIRE_PROGS(AWK, [gawk nawk awk]) UTIL_REQUIRE_PROGS(PRINTF, printf) UTIL_REQUIRE_PROGS(READLINK, [greadlink readlink]) UTIL_REQUIRE_PROGS(RM, rm) @@ -75,7 +75,6 @@ AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS], UTIL_REQUIRE_PROGS(XARGS, xargs) # Then required tools that require some special treatment. - UTIL_REQUIRE_SPECIAL(AWK, [AC_PROG_AWK]) UTIL_REQUIRE_SPECIAL(GREP, [AC_PROG_GREP]) UTIL_REQUIRE_SPECIAL(EGREP, [AC_PROG_EGREP]) UTIL_REQUIRE_SPECIAL(FGREP, [AC_PROG_FGREP]) diff --git a/make/autoconf/compare.sh.in b/make/autoconf/compare.sh.in index a57262689d3..e5f5ba679a1 100644 --- a/make/autoconf/compare.sh.in +++ b/make/autoconf/compare.sh.in @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -53,7 +53,6 @@ export LDD="@LDD@" export LN="@LN@" export MKDIR="@MKDIR@" export MV="@MV@" -export NAWK="@NAWK@" export NM="@GNM@" export OBJDUMP="@OBJDUMP@" export OTOOL="@OTOOL@" diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in index b58ac1193df..2db742886d0 100644 --- a/make/autoconf/spec.gmk.in +++ b/make/autoconf/spec.gmk.in @@ -709,7 +709,6 @@ LN:=@LN@ MIG:=@MIG@ MKDIR:=@MKDIR@ MV:=@MV@ -NAWK:=@NAWK@ NICE:=@NICE@ PANDOC:=@FIXPATH@ @PANDOC@ PATCH:=@PATCH@ diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk index ea6f9f41bc7..7efd9009eb6 100644 --- a/make/common/MakeBase.gmk +++ b/make/common/MakeBase.gmk @@ -89,7 +89,7 @@ BUILDTIMESDIR=$(OUTPUTDIR)/make-support/build-times # Record starting time for build of a sub repository. define RecordStartTime - $(DATE) '+%Y %m %d %H %M %S' | $(NAWK) '{ print $$1,$$2,$$3,$$4,$$5,$$6,($$4*3600+$$5*60+$$6) }' > $(BUILDTIMESDIR)/build_time_start_$(strip $1) && \ + $(DATE) '+%Y %m %d %H %M %S' | $(AWK) '{ print $$1,$$2,$$3,$$4,$$5,$$6,($$4*3600+$$5*60+$$6) }' > $(BUILDTIMESDIR)/build_time_start_$(strip $1) && \ $(DATE) '+%Y-%m-%d %H:%M:%S' > $(BUILDTIMESDIR)/build_time_start_$(strip $1)_human_readable endef @@ -97,10 +97,10 @@ endef # easy to read format. Handles builds that cross midnight. Expects # that a build will never take 24 hours or more. define RecordEndTime - $(DATE) '+%Y %m %d %H %M %S' | $(NAWK) '{ print $$1,$$2,$$3,$$4,$$5,$$6,($$4*3600+$$5*60+$$6) }' > $(BUILDTIMESDIR)/build_time_end_$(strip $1) + $(DATE) '+%Y %m %d %H %M %S' | $(AWK) '{ print $$1,$$2,$$3,$$4,$$5,$$6,($$4*3600+$$5*60+$$6) }' > $(BUILDTIMESDIR)/build_time_end_$(strip $1) $(DATE) '+%Y-%m-%d %H:%M:%S' > $(BUILDTIMESDIR)/build_time_end_$(strip $1)_human_readable $(ECHO) `$(CAT) $(BUILDTIMESDIR)/build_time_start_$(strip $1)` `$(CAT) $(BUILDTIMESDIR)/build_time_end_$(strip $1)` $1 | \ - $(NAWK) '{ F=$$7; T=$$14; if (F > T) { T+=3600*24 }; D=T-F; H=int(D/3600); \ + $(AWK) '{ F=$$7; T=$$14; if (F > T) { T+=3600*24 }; D=T-F; H=int(D/3600); \ M=int((D-H*3600)/60); S=D-H*3600-M*60; printf("%02d:%02d:%02d %s\n",H,M,S,$$15); }' \ > $(BUILDTIMESDIR)/build_time_diff_$(strip $1) endef @@ -439,6 +439,8 @@ endif # This is normally not needed since we use the FIXPATH prefix for command lines, # but might be needed in certain circumstances. ifeq ($(call isTargetOs, windows), true) + FixPathArgs = \ + $(shell $(FIXPATH) cmd /c echo $1) ifeq ($(call isBuildOsEnv, windows.wsl), true) FixPath = \ $(shell $(WSLPATH) -m $1) @@ -447,6 +449,8 @@ ifeq ($(call isTargetOs, windows), true) $(shell $(CYGPATH) -m $1) endif else + FixPathArgs = \ + $1 FixPath = \ $1 endif diff --git a/make/common/Modules.gmk b/make/common/Modules.gmk index 10aacff4726..910f8beb2ff 100644 --- a/make/common/Modules.gmk +++ b/make/common/Modules.gmk @@ -338,7 +338,7 @@ $(MODULE_DEPS_MAKEFILE): $(MODULE_INFOS) \ $(RM) $@ $(foreach m, $(MODULE_INFOS), \ ( $(PRINTF) "DEPS_$(call GetModuleNameFromModuleInfo, $m) :=" && \ - $(NAWK) -v MODULE=$(call GetModuleNameFromModuleInfo, $m) '\ + $(AWK) -v MODULE=$(call GetModuleNameFromModuleInfo, $m) '\ BEGIN { if (MODULE != "java.base") printf(" java.base"); } \ /^ *requires/ { sub(/;/, ""); \ sub(/requires /, " "); \ @@ -352,7 +352,7 @@ $(MODULE_DEPS_MAKEFILE): $(MODULE_INFOS) \ printf(" %s", $$0) } \ END { printf("\n") }' $m && \ $(PRINTF) "TRANSITIVE_MODULES_$(call GetModuleNameFromModuleInfo, $m) :=" && \ - $(NAWK) -v MODULE=$(call GetModuleNameFromModuleInfo, $m) '\ + $(AWK) -v MODULE=$(call GetModuleNameFromModuleInfo, $m) '\ BEGIN { if (MODULE != "java.base") printf(" java.base"); } \ /^ *requires *transitive/ { \ sub(/;/, ""); \ diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index d4c202146e0..0472ec38021 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -72,10 +72,10 @@ define WriteCompileCommandsFragment $(call LogInfo, Creating compile commands fragment for $(notdir $3)) $(call MakeDir, $(dir $1)) $(call WriteFile,{ \ - "directory": "$(strip $2)"$(COMMA) \ - "file": "$(strip $3)"$(COMMA) \ + "directory": "$(strip $(call FixPathArgs, $2))"$(COMMA) \ + "file": "$(strip $(call FixPathArgs, $3))"$(COMMA) \ "command": "$(strip $(subst $(DQUOTE),\$(DQUOTE),$(subst \,\\,\ - $(subst $(FIXPATH),,$4))))" \ + $(subst $(FIXPATH),,$(call FixPathArgs, $4)))))" \ }$(COMMA), \ $1) endef @@ -237,10 +237,15 @@ ifeq ($(ALLOW_ABSOLUTE_PATHS_IN_OUTPUT)-$(FILE_MACRO_CFLAGS), false-) ) \ ) - # When compiling with relative paths, the deps file comes out with relative - # paths. + # When compiling with relative paths, the deps file may come out with relative + # paths, and that path may start with './'. First remove any leading ./, then + # add WORKSPACE_ROOT to any line not starting with /, while allowing for + # leading spaces. define fix-deps-file - $(SED) -e 's|^\([ ]*\)|\1$(WORKSPACE_ROOT)|' $1.tmp > $1 + $(SED) \ + -e 's|^\([ ]*\)\./|\1|' \ + -e '/^[ ]*[^/ ]/s|^\([ ]*\)|\1$(WORKSPACE_ROOT)/|' \ + $1.tmp > $1 endef else # By default the MakeCommandRelative macro does nothing. diff --git a/make/common/TextFileProcessing.gmk b/make/common/TextFileProcessing.gmk index 7308d7e8c19..79df3eec40e 100644 --- a/make/common/TextFileProcessing.gmk +++ b/make/common/TextFileProcessing.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2020, 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 @@ -177,7 +177,7 @@ define SetupTextFileProcessingBody $1_INCLUDES_PARTIAL_AWK := $$(subst $$(SPACE);,,$$(subst $$(SPACE)=>$$(SPACE),"$$(RIGHT_PAREN)$$(RIGHT_PAREN) \ { include$$(LEFT_PAREN)",$$(subst $$(SPACE);$$(SPACE),"$$(RIGHT_PAREN) } \ else if $$(LEFT_PAREN)matches$$(LEFT_PAREN)",$$(strip $$($1_INCLUDES))))) - $1_INCLUDES_COMMAND_LINE := $(NAWK) '$$($1_INCLUDES_HEADER_AWK) \ + $1_INCLUDES_COMMAND_LINE := $(AWK) '$$($1_INCLUDES_HEADER_AWK) \ { if (matches("$$($1_INCLUDES_PARTIAL_AWK)") } else print }' else # We don't have any includes, just pipe the file through cat. diff --git a/make/hotspot/gensrc/GensrcAdlc.gmk b/make/hotspot/gensrc/GensrcAdlc.gmk index fb7d48f1e27..149bdaa4ea6 100644 --- a/make/hotspot/gensrc/GensrcAdlc.gmk +++ b/make/hotspot/gensrc/GensrcAdlc.gmk @@ -168,7 +168,7 @@ ifeq ($(call check-jvm-feature, compiler2), true) $(SINGLE_AD_SRCFILE): $(AD_SRC_FILES) $(call LogInfo, Preprocessing adlc files $(^F)) $(call MakeDir, $(@D)) - $(NAWK) $(INSERT_FILENAME_AWK_SCRIPT) $^ > $@ + $(AWK) $(INSERT_FILENAME_AWK_SCRIPT) $^ > $@ ############################################################################## # Run the adlc tool on the single concatenated ad source file, and store the @@ -205,7 +205,7 @@ ifeq ($(call check-jvm-feature, compiler2), true) $(JVM_VARIANT_OUTPUTDIR)/gensrc/adfiles/%: $(adlc_run_TARGET) $(call LogInfo, Postprocessing adlc file $*) $(call MakeDir, $(@D)) - $(NAWK) \ + $(AWK) \ 'BEGIN { print "#line 1 \"$*\""; } \ /^#line 999999$$/ {print "#line " (NR+1) " \"$*\""; next} \ $(if $(call equals, $(ALLOW_ABSOLUTE_PATHS_IN_OUTPUT), false), \ diff --git a/make/hotspot/lib/JvmMapfile.gmk b/make/hotspot/lib/JvmMapfile.gmk index c75eecd3ced..7da46ebe699 100644 --- a/make/hotspot/lib/JvmMapfile.gmk +++ b/make/hotspot/lib/JvmMapfile.gmk @@ -114,7 +114,7 @@ endif $(JVM_OUTPUTDIR)/symbols-objects: $(BUILD_LIBJVM_ALL_OBJS) $(call LogInfo, Generating symbol list from object files) $(CD) $(JVM_OUTPUTDIR)/objs && \ - $(DUMP_SYMBOLS_CMD) | $(NAWK) $(FILTER_SYMBOLS_AWK_SCRIPT) | $(SORT) -u > $@ + $(DUMP_SYMBOLS_CMD) | $(AWK) $(FILTER_SYMBOLS_AWK_SCRIPT) | $(SORT) -u > $@ SYMBOLS_SRC += $(JVM_OUTPUTDIR)/symbols-objects diff --git a/make/modules/java.base/gensrc/GensrcExceptions.gmk b/make/modules/java.base/gensrc/GensrcExceptions.gmk index fd7d8c75d8b..37fed896560 100644 --- a/make/modules/java.base/gensrc/GensrcExceptions.gmk +++ b/make/modules/java.base/gensrc/GensrcExceptions.gmk @@ -36,7 +36,7 @@ $(GENSRC_EXCEPTIONS_DST)/_the.%.marker: $(GENSRC_EXCEPTIONS_SRC)/%/exceptions \ $(GENSRC_EXCEPTIONS_CMD) $(call LogInfo, Generating exceptions java.nio $*) $(call MakeDir, $(@D)/$*) - SCRIPTS="$(TOPDIR)/make/scripts" NAWK="$(NAWK)" SH="$(SH)" $(SH) \ + SCRIPTS="$(TOPDIR)/make/scripts" AWK="$(AWK)" SH="$(SH)" $(SH) \ $(GENSRC_EXCEPTIONS_CMD) $< $(@D)/$* $(LOG_DEBUG) $(TOUCH) $@ diff --git a/make/modules/java.base/gensrc/GensrcMisc.gmk b/make/modules/java.base/gensrc/GensrcMisc.gmk index 31d816d1e34..3519b0216ae 100644 --- a/make/modules/java.base/gensrc/GensrcMisc.gmk +++ b/make/modules/java.base/gensrc/GensrcMisc.gmk @@ -78,10 +78,10 @@ endif define generate-preproc-src $(call MakeDir, $(@D)) $(call ExecuteWithLog, $(SUPPORT_OUTPUTDIR)/gensrc/java.base/_$(@F), \ - ( $(NAWK) '/@@END_COPYRIGHT@@/{exit}1' $< && \ + ( $(AWK) '/@@END_COPYRIGHT@@/{exit}1' $< && \ $(CPP) $(CPP_FLAGS) $(SYSROOT_CFLAGS) $(CFLAGS_JDKLIB) $(CPP_FILEPREFIX) $< \ 2> >($(GREP) -v '^$(&2) \ - | $(NAWK) '/@@START_HERE@@/,0' \ + | $(AWK) '/@@START_HERE@@/,0' \ | $(SED) -e 's/@@START_HERE@@/\/\/ AUTOMATICALLY GENERATED FILE - DO NOT EDIT/' \ -e 's/PREFIX_//' -e 's/^#.*//' \ ) > $@ \ diff --git a/make/modules/jdk.internal.vm.compiler.management/Gensrc.gmk b/make/modules/jdk.internal.vm.compiler.management/Gensrc.gmk index 103b2bba503..8a842997d76 100644 --- a/make/modules/jdk.internal.vm.compiler.management/Gensrc.gmk +++ b/make/modules/jdk.internal.vm.compiler.management/Gensrc.gmk @@ -68,7 +68,7 @@ $(GENSRC_DIR)/module-info.java.extra: $(GENSRC_DIR)/_gensrc_proc_done ($(CD) $(GENSRC_DIR)/META-INF/providers && \ p=""; \ impl=""; \ - for i in $$($(NAWK) '$$0=FILENAME" "$$0' * | $(SORT) -k 2 | $(SED) 's/ .*//'); do \ + for i in $$($(AWK) '$$0=FILENAME" "$$0' * | $(SORT) -k 2 | $(SED) 's/ .*//'); do \ c=$$($(CAT) $$i | $(TR) -d '\n\r'); \ if test x$$p != x$$c; then \ if test x$$p != x; then \ diff --git a/make/scripts/addNotices.sh b/make/scripts/addNotices.sh index 6e0cdf916af..d9864818a14 100644 --- a/make/scripts/addNotices.sh +++ b/make/scripts/addNotices.sh @@ -1,6 +1,6 @@ #! /bin/sh # -# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 2020, 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 @@ -40,6 +40,6 @@ if [ "x$COPYRIGHT_YEARS" != x ]; then __END__ fi -$NAWK ' /^#.*Copyright.*Oracle/ { next } +$AWK ' /^#.*Copyright.*Oracle/ { next } /^#([^!]|$)/ { sub(/^#/, " *"); print } /^$/ { print " */"; exit } ' $0 diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 4e7ec289985..a46845d81f5 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -1311,9 +1311,10 @@ void VM_Version::get_processor_features() { } #endif // COMPILER2 - // Some defaults for AMD family 17h || Hygon family 18h - if (cpu_family() == 0x17 || cpu_family() == 0x18) { - // On family 17h processors use XMM and UnalignedLoadStores for Array Copy + // Some defaults for AMD family >= 17h && Hygon family 18h + if (cpu_family() >= 0x17) { + // On family >=17h processors use XMM and UnalignedLoadStores + // for Array Copy if (supports_sse2() && FLAG_IS_DEFAULT(UseXMMForArrayCopy)) { FLAG_SET_DEFAULT(UseXMMForArrayCopy, true); } @@ -1519,6 +1520,14 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseFastStosb, false); } + // For AMD Processors use XMM/YMM MOVDQU instructions + // for Object Initialization as default + if (is_amd() && cpu_family() >= 0x19) { + if (FLAG_IS_DEFAULT(UseFastStosb)) { + UseFastStosb = false; + } + } + // Use XMM/YMM MOVDQU instruction for Object Initialization if (!UseFastStosb && UseSSE >= 2 && UseUnalignedLoadStores) { if (FLAG_IS_DEFAULT(UseXMMForObjInit)) { diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index a49c3861cbf..eff37d445c6 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -3726,6 +3726,10 @@ instruct ReplB_reg(vec dst, rRegI src) %{ assert(VM_Version::supports_avx512bw(), "required"); // 512-bit byte vectors assume AVX512BW int vlen_enc = vector_length_encoding(this); __ evpbroadcastb($dst$$XMMRegister, $src$$Register, vlen_enc); + } else if (VM_Version::supports_avx2()) { + int vlen_enc = vector_length_encoding(this); + __ movdl($dst$$XMMRegister, $src$$Register); + __ vpbroadcastb($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); } else { __ movdl($dst$$XMMRegister, $src$$Register); __ punpcklbw($dst$$XMMRegister, $dst$$XMMRegister); @@ -3805,6 +3809,10 @@ instruct ReplS_reg(vec dst, rRegI src) %{ assert(VM_Version::supports_avx512bw(), "required"); // 512-bit short vectors assume AVX512BW int vlen_enc = vector_length_encoding(this); __ evpbroadcastw($dst$$XMMRegister, $src$$Register, vlen_enc); + } else if (VM_Version::supports_avx2()) { + int vlen_enc = vector_length_encoding(this); + __ movdl($dst$$XMMRegister, $src$$Register); + __ vpbroadcastw($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); } else { __ movdl($dst$$XMMRegister, $src$$Register); __ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00); @@ -3880,6 +3888,10 @@ instruct ReplI_reg(vec dst, rRegI src) %{ if (vlen == 16 || VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands int vlen_enc = vector_length_encoding(this); __ evpbroadcastd($dst$$XMMRegister, $src$$Register, vlen_enc); + } else if (VM_Version::supports_avx2()) { + int vlen_enc = vector_length_encoding(this); + __ movdl($dst$$XMMRegister, $src$$Register); + __ vpbroadcastd($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); } else { __ movdl($dst$$XMMRegister, $src$$Register); __ pshufd($dst$$XMMRegister, $dst$$XMMRegister, 0x00); @@ -3975,6 +3987,11 @@ instruct ReplL_reg(vec dst, rRegL src) %{ } else if (vlen == 8 || VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands int vlen_enc = vector_length_encoding(this); __ evpbroadcastq($dst$$XMMRegister, $src$$Register, vlen_enc); + } else if (VM_Version::supports_avx2()) { + assert(vlen == 4, "sanity"); + int vlen_enc = vector_length_encoding(this); + __ movdq($dst$$XMMRegister, $src$$Register); + __ vpbroadcastq($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); } else { assert(vlen == 4, "sanity"); __ movdq($dst$$XMMRegister, $src$$Register); diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index 0e285b412a2..6871f6bd6a8 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -2464,8 +2464,6 @@ void os::init(void) { clock_tics_per_sec = sysconf(_SC_CLK_TCK); - init_random(1234567); - // _main_thread points to the thread that created/loaded the JVM. Aix::_main_thread = pthread_self(); diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index b28f233652d..733e2b7e0e7 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -2089,8 +2089,6 @@ void os::init(void) { clock_tics_per_sec = CLK_TCK; - init_random(1234567); - Bsd::set_page_size(getpagesize()); if (Bsd::page_size() == -1) { fatal("os_bsd.cpp: os::init: sysconf failed (%s)", os::strerror(errno)); diff --git a/src/hotspot/os/bsd/semaphore_bsd.cpp b/src/hotspot/os/bsd/semaphore_bsd.cpp index b13e0c47ed0..012b5b8ed91 100644 --- a/src/hotspot/os/bsd/semaphore_bsd.cpp +++ b/src/hotspot/os/bsd/semaphore_bsd.cpp @@ -22,7 +22,7 @@ * */ -#include "precompiled/precompiled.hpp" +#include "precompiled.hpp" #include "semaphore_bsd.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 701a1fa44a2..15d1dff4d84 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -4394,8 +4394,6 @@ void os::init(void) { clock_tics_per_sec = sysconf(_SC_CLK_TCK); - init_random(1234567); - Linux::set_page_size(sysconf(_SC_PAGESIZE)); if (Linux::page_size() == -1) { fatal("os_linux.cpp: os::init: sysconf failed (%s)", diff --git a/src/hotspot/os/linux/waitBarrier_linux.cpp b/src/hotspot/os/linux/waitBarrier_linux.cpp index 88cf1e7b3c6..491f9e6b866 100644 --- a/src/hotspot/os/linux/waitBarrier_linux.cpp +++ b/src/hotspot/os/linux/waitBarrier_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ * */ -#include "precompiled/precompiled.hpp" +#include "precompiled.hpp" #include "runtime/orderAccess.hpp" #include "runtime/os.hpp" #include "waitBarrier_linux.hpp" diff --git a/src/hotspot/os/posix/semaphore_posix.cpp b/src/hotspot/os/posix/semaphore_posix.cpp index fa37c7b0fed..95cd6f1220e 100644 --- a/src/hotspot/os/posix/semaphore_posix.cpp +++ b/src/hotspot/os/posix/semaphore_posix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ * */ -#include "precompiled/precompiled.hpp" +#include "precompiled.hpp" #ifndef __APPLE__ #include "runtime/os.hpp" // POSIX unamed semaphores are not supported on OS X. diff --git a/src/hotspot/os/posix/signals_posix.cpp b/src/hotspot/os/posix/signals_posix.cpp index b7a9cb55156..02be4bace9e 100644 --- a/src/hotspot/os/posix/signals_posix.cpp +++ b/src/hotspot/os/posix/signals_posix.cpp @@ -22,7 +22,7 @@ * */ -#include "precompiled/precompiled.hpp" +#include "precompiled.hpp" #include "jvm.h" #include "logging/log.hpp" diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 2a9a7f82d2a..3342ecf7817 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4164,8 +4164,6 @@ void nx_check_protection() { void os::init(void) { _initial_pid = _getpid(); - init_random(1234567); - win32::initialize_system_info(); win32::setmode_streams(); init_page_sizes((size_t) win32::vm_page_size()); diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index f18393e1488..43b969df45c 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -52,6 +52,7 @@ #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/g1ParallelCleaning.hpp" #include "gc/g1/g1ParScanThreadState.inline.hpp" +#include "gc/g1/g1PeriodicGCTask.hpp" #include "gc/g1/g1Policy.hpp" #include "gc/g1/g1RedirtyCardsQueue.hpp" #include "gc/g1/g1RegionToSpaceMapper.hpp" @@ -1390,6 +1391,7 @@ class HumongousRegionSetChecker : public HeapRegionSetChecker { G1CollectedHeap::G1CollectedHeap() : CollectedHeap(), _service_thread(NULL), + _periodic_gc_task(NULL), _workers(NULL), _card_table(NULL), _collection_pause_end(Ticks::now()), @@ -1689,6 +1691,10 @@ jint G1CollectedHeap::initialize() { // Initialize and schedule sampling task on service thread. _rem_set->initialize_sampling_task(service_thread()); + // Create and schedule the periodic gc task on the service thread. + _periodic_gc_task = new G1PeriodicGCTask("Periodic GC Task"); + _service_thread->register_task(_periodic_gc_task); + { G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); dcqs.set_process_cards_threshold(concurrent_refine()->yellow_zone()); diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 20f33e0817c..51baca7ef48 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -79,6 +79,7 @@ class G1CollectionSet; class G1Policy; class G1HotCardCache; class G1RemSet; +class G1ServiceTask; class G1ServiceThread; class G1ConcurrentMark; class G1ConcurrentMarkThread; @@ -154,6 +155,7 @@ class G1CollectedHeap : public CollectedHeap { private: G1ServiceThread* _service_thread; + G1ServiceTask* _periodic_gc_task; WorkGang* _workers; G1CardTable* _card_table; diff --git a/src/hotspot/share/gc/g1/g1PeriodicGCTask.cpp b/src/hotspot/share/gc/g1/g1PeriodicGCTask.cpp new file mode 100644 index 00000000000..67ddc6c49a4 --- /dev/null +++ b/src/hotspot/share/gc/g1/g1PeriodicGCTask.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2020, 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. + * + */ + +#include "precompiled.hpp" +#include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1ConcurrentMark.inline.hpp" +#include "gc/g1/g1ConcurrentMarkThread.inline.hpp" +#include "gc/g1/g1PeriodicGCTask.hpp" +#include "logging/log.hpp" +#include "runtime/globals.hpp" +#include "runtime/os.hpp" +#include "utilities/globalDefinitions.hpp" + +bool G1PeriodicGCTask::should_start_periodic_gc() { + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + // If we are currently in a concurrent mark we are going to uncommit memory soon. + if (g1h->concurrent_mark()->cm_thread()->in_progress()) { + log_debug(gc, periodic)("Concurrent cycle in progress. Skipping."); + return false; + } + + // Check if enough time has passed since the last GC. + uintx time_since_last_gc = (uintx)g1h->time_since_last_collection().milliseconds(); + if ((time_since_last_gc < G1PeriodicGCInterval)) { + log_debug(gc, periodic)("Last GC occurred " UINTX_FORMAT "ms before which is below threshold " UINTX_FORMAT "ms. Skipping.", + time_since_last_gc, G1PeriodicGCInterval); + return false; + } + + // Check if load is lower than max. + double recent_load; + if ((G1PeriodicGCSystemLoadThreshold > 0.0f) && + (os::loadavg(&recent_load, 1) == -1 || recent_load > G1PeriodicGCSystemLoadThreshold)) { + log_debug(gc, periodic)("Load %1.2f is higher than threshold %1.2f. Skipping.", + recent_load, G1PeriodicGCSystemLoadThreshold); + return false; + } + return true; +} + +void G1PeriodicGCTask::check_for_periodic_gc() { + // If disabled, just return. + if (G1PeriodicGCInterval == 0) { + return; + } + + log_debug(gc, periodic)("Checking for periodic GC."); + if (should_start_periodic_gc()) { + if (!G1CollectedHeap::heap()->try_collect(GCCause::_g1_periodic_collection)) { + log_debug(gc, periodic)("GC request denied. Skipping."); + } + } +} + +G1PeriodicGCTask::G1PeriodicGCTask(const char* name) : + G1ServiceTask(name) { } + +void G1PeriodicGCTask::execute() { + check_for_periodic_gc(); + // G1PeriodicGCInterval is a manageable flag and can be updated + // during runtime. If no value is set, wait a second and run it + // again to see if the value has been updated. Otherwise use the + // real value provided. + schedule(G1PeriodicGCInterval == 0 ? 1000 : G1PeriodicGCInterval); +} diff --git a/src/hotspot/share/gc/g1/g1PeriodicGCTask.hpp b/src/hotspot/share/gc/g1/g1PeriodicGCTask.hpp new file mode 100644 index 00000000000..237968898c4 --- /dev/null +++ b/src/hotspot/share/gc/g1/g1PeriodicGCTask.hpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020, 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. + * + */ + +#ifndef SHARE_GC_G1_G1PERIODICGCTASK_HPP +#define SHARE_GC_G1_G1PERIODICGCTASK_HPP + +#include "gc/g1/g1ServiceThread.hpp" + +// Task handling periodic GCs +class G1PeriodicGCTask : public G1ServiceTask { + bool should_start_periodic_gc(); + void check_for_periodic_gc(); + +public: + G1PeriodicGCTask(const char* name); + virtual void execute(); +}; + +#endif // SHARE_GC_G1_G1PERIODICGCTASK_HPP \ No newline at end of file diff --git a/src/hotspot/share/gc/g1/g1ServiceThread.cpp b/src/hotspot/share/gc/g1/g1ServiceThread.cpp index 012c8b71b3c..7b39b7d2808 100644 --- a/src/hotspot/share/gc/g1/g1ServiceThread.cpp +++ b/src/hotspot/share/gc/g1/g1ServiceThread.cpp @@ -23,12 +23,10 @@ */ #include "precompiled.hpp" -#include "gc/g1/g1CollectedHeap.inline.hpp" -#include "gc/g1/g1ConcurrentMark.inline.hpp" -#include "gc/g1/g1ConcurrentMarkThread.inline.hpp" #include "gc/g1/g1ServiceThread.hpp" -#include "memory/universe.hpp" +#include "logging/log.hpp" #include "runtime/mutexLocker.hpp" +#include "runtime/timer.hpp" #include "runtime/os.hpp" G1SentinelTask::G1SentinelTask() : G1ServiceTask("Sentinel Task") { @@ -40,77 +38,17 @@ void G1SentinelTask::execute() { guarantee(false, "Sentinel service task should never be executed."); } -// Task handling periodic GCs -class G1PeriodicGCTask : public G1ServiceTask { - bool should_start_periodic_gc() { - G1CollectedHeap* g1h = G1CollectedHeap::heap(); - // If we are currently in a concurrent mark we are going to uncommit memory soon. - if (g1h->concurrent_mark()->cm_thread()->in_progress()) { - log_debug(gc, periodic)("Concurrent cycle in progress. Skipping."); - return false; - } - - // Check if enough time has passed since the last GC. - uintx time_since_last_gc = (uintx)g1h->time_since_last_collection().milliseconds(); - if ((time_since_last_gc < G1PeriodicGCInterval)) { - log_debug(gc, periodic)("Last GC occurred " UINTX_FORMAT "ms before which is below threshold " UINTX_FORMAT "ms. Skipping.", - time_since_last_gc, G1PeriodicGCInterval); - return false; - } - - // Check if load is lower than max. - double recent_load; - if ((G1PeriodicGCSystemLoadThreshold > 0.0f) && - (os::loadavg(&recent_load, 1) == -1 || recent_load > G1PeriodicGCSystemLoadThreshold)) { - log_debug(gc, periodic)("Load %1.2f is higher than threshold %1.2f. Skipping.", - recent_load, G1PeriodicGCSystemLoadThreshold); - return false; - } - return true; - } - - void check_for_periodic_gc(){ - // If disabled, just return. - if (G1PeriodicGCInterval == 0) { - return; - } - - log_debug(gc, periodic)("Checking for periodic GC."); - if (should_start_periodic_gc()) { - if (!G1CollectedHeap::heap()->try_collect(GCCause::_g1_periodic_collection)) { - log_debug(gc, periodic)("GC request denied. Skipping."); - } - } - } -public: - G1PeriodicGCTask(const char* name) : G1ServiceTask(name) { } - - virtual void execute() { - check_for_periodic_gc(); - // G1PeriodicGCInterval is a manageable flag and can be updated - // during runtime. If no value is set, wait a second and run it - // again to see if the value has been updated. Otherwise use the - // real value provided. - schedule(G1PeriodicGCInterval == 0 ? 1000 : G1PeriodicGCInterval); - } -}; - G1ServiceThread::G1ServiceThread() : ConcurrentGCThread(), _monitor(Mutex::nonleaf, "G1ServiceThread monitor", true, Monitor::_safepoint_check_never), - _task_queue(), - _periodic_gc_task(new G1PeriodicGCTask("Periodic GC Task")) { + _task_queue() { set_name("G1 Service"); create_and_start(); } -G1ServiceThread::~G1ServiceThread() { - delete _periodic_gc_task; -} - void G1ServiceThread::register_task(G1ServiceTask* task, jlong delay_ms) { guarantee(!task->is_registered(), "Task already registered"); guarantee(task->next() == NULL, "Task already in queue"); @@ -215,9 +153,6 @@ void G1ServiceThread::run_task(G1ServiceTask* task) { } void G1ServiceThread::run_service() { - // Register the tasks handled by the service thread. - register_task(_periodic_gc_task); - while (!should_terminate()) { G1ServiceTask* task = pop_due_task(); if (task != NULL) { diff --git a/src/hotspot/share/gc/g1/g1ServiceThread.hpp b/src/hotspot/share/gc/g1/g1ServiceThread.hpp index df6bdee2d2c..73457488eb0 100644 --- a/src/hotspot/share/gc/g1/g1ServiceThread.hpp +++ b/src/hotspot/share/gc/g1/g1ServiceThread.hpp @@ -28,7 +28,6 @@ #include "gc/shared/concurrentGCThread.hpp" #include "runtime/mutex.hpp" -class G1PeriodicGCTask; class G1ServiceTaskQueue; class G1ServiceThread; @@ -105,8 +104,6 @@ class G1ServiceThread: public ConcurrentGCThread { Monitor _monitor; G1ServiceTaskQueue _task_queue; - G1PeriodicGCTask* _periodic_gc_task; - void run_service(); void stop_service(); @@ -129,7 +126,6 @@ class G1ServiceThread: public ConcurrentGCThread { public: G1ServiceThread(); - ~G1ServiceThread(); // Register a task with the service thread. The task is guaranteed not to run // until at least `delay_ms` has passed. If no delay is specified or the diff --git a/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp index 04ae460e7b6..8cda596e316 100644 --- a/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp +++ b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp @@ -37,6 +37,27 @@ size_t ThreadLocalAllocBuffer::_max_size = 0; int ThreadLocalAllocBuffer::_reserve_for_allocation_prefetch = 0; unsigned int ThreadLocalAllocBuffer::_target_refills = 0; +ThreadLocalAllocBuffer::ThreadLocalAllocBuffer() : + _start(NULL), + _top(NULL), + _pf_top(NULL), + _end(NULL), + _allocation_end(NULL), + _desired_size(0), + _refill_waste_limit(0), + _allocated_before_last_gc(0), + _bytes_since_last_sample_point(0), + _number_of_refills(0), + _fast_refill_waste(0), + _slow_refill_waste(0), + _gc_waste(0), + _slow_allocations(0), + _allocated_size(0), + _allocation_fraction(TLABAllocationWeight) { + + // do nothing. TLABs must be inited by initialize() calls +} + size_t ThreadLocalAllocBuffer::remaining() { if (end() == NULL) { return 0; diff --git a/src/hotspot/share/gc/shared/threadLocalAllocBuffer.hpp b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.hpp index 3e875d32384..51d97270850 100644 --- a/src/hotspot/share/gc/shared/threadLocalAllocBuffer.hpp +++ b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.hpp @@ -111,10 +111,7 @@ class ThreadLocalAllocBuffer: public CHeapObj { int slow_allocations() const { return _slow_allocations; } public: - ThreadLocalAllocBuffer() : _allocated_before_last_gc(0), _bytes_since_last_sample_point(0), - _allocation_fraction(TLABAllocationWeight) { - // do nothing. tlabs must be inited by initialize() calls - } + ThreadLocalAllocBuffer(); static size_t min_size() { return align_object_size(MinTLABSize / HeapWordSize) + alignment_reserve(); } static size_t max_size() { assert(_max_size != 0, "max_size not set up"); return _max_size; } diff --git a/src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.cpp b/src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.cpp index c63f4c91cc7..95ff610bdf6 100644 --- a/src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.cpp +++ b/src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.cpp @@ -103,8 +103,8 @@ class JfrChunkHeadWriter : public StackObj { _writer->be_write(PAD); } - void write_next_generation() { - _writer->be_write(_chunk->next_generation()); + void write_next_generation(bool finalize) { + _writer->be_write(finalize ? COMPLETE : _chunk->next_generation()); _writer->be_write(PAD); } @@ -199,9 +199,9 @@ int64_t JfrChunkWriter::write_chunk_header_checkpoint(bool flushpoint) { const int64_t chunk_size_offset = reserve(sizeof(int64_t)); // size to be decided when we are done be_write(event_size_offset); // last checkpoint offset will be this checkpoint head.write_metadata(); - head.write_time(false); + head.write_time(!flushpoint); head.write_cpu_frequency(); - head.write_next_generation(); + head.write_next_generation(!flushpoint); head.write_flags(); assert(current_offset() - header_content_pos == HEADER_SIZE, "invariant"); const u4 checkpoint_size = current_offset() - event_size_offset; diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index 902eda16d31..90d221964cd 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -2956,7 +2956,7 @@ LoadStoreNode::LoadStoreNode( Node *c, Node *mem, Node *adr, Node *val, const Ty : Node(required), _type(rt), _adr_type(at), - _barrier(0) + _barrier_data(0) { init_req(MemNode::Control, c ); init_req(MemNode::Memory , mem); diff --git a/src/hotspot/share/opto/memnode.hpp b/src/hotspot/share/opto/memnode.hpp index 1b0ba11b546..b9ee30fe30c 100644 --- a/src/hotspot/share/opto/memnode.hpp +++ b/src/hotspot/share/opto/memnode.hpp @@ -43,7 +43,7 @@ class MemNode : public Node { bool _unaligned_access; // Unaligned access from unsafe bool _mismatched_access; // Mismatched access from unsafe: byte read in integer array for instance bool _unsafe_access; // Access of unsafe origin. - uint8_t _barrier; // Bit field with barrier information + uint8_t _barrier_data; // Bit field with barrier information protected: #ifdef ASSERT @@ -69,7 +69,7 @@ class MemNode : public Node { _unaligned_access(false), _mismatched_access(false), _unsafe_access(false), - _barrier(0) { + _barrier_data(0) { init_class_id(Class_Mem); debug_only(_adr_type=at; adr_type();) } @@ -78,7 +78,7 @@ class MemNode : public Node { _unaligned_access(false), _mismatched_access(false), _unsafe_access(false), - _barrier(0) { + _barrier_data(0) { init_class_id(Class_Mem); debug_only(_adr_type=at; adr_type();) } @@ -87,7 +87,7 @@ class MemNode : public Node { _unaligned_access(false), _mismatched_access(false), _unsafe_access(false), - _barrier(0) { + _barrier_data(0) { init_class_id(Class_Mem); debug_only(_adr_type=at; adr_type();) } @@ -140,8 +140,8 @@ class MemNode : public Node { #endif } - uint8_t barrier_data() { return _barrier; } - void set_barrier_data(uint8_t barrier_data) { _barrier = barrier_data; } + uint8_t barrier_data() { return _barrier_data; } + void set_barrier_data(uint8_t barrier_data) { _barrier_data = barrier_data; } // Search through memory states which precede this node (load or store). // Look for an exact match for the address, with no intervening @@ -839,7 +839,7 @@ class LoadStoreNode : public Node { private: const Type* const _type; // What kind of value is loaded? const TypePtr* _adr_type; // What kind of memory is being addressed? - uint8_t _barrier; // Bit field with barrier information + uint8_t _barrier_data; // Bit field with barrier information virtual uint size_of() const; // Size is bigger public: LoadStoreNode( Node *c, Node *mem, Node *adr, Node *val, const TypePtr* at, const Type* rt, uint required ); @@ -853,8 +853,8 @@ class LoadStoreNode : public Node { bool result_not_used() const; MemBarNode* trailing_membar() const; - uint8_t barrier_data() { return _barrier; } - void set_barrier_data(uint8_t barrier_data) { _barrier = barrier_data; } + uint8_t barrier_data() { return _barrier_data; } + void set_barrier_data(uint8_t barrier_data) { _barrier_data = barrier_data; } }; class LoadStoreConditionalNode : public LoadStoreNode { diff --git a/src/hotspot/share/opto/regmask.cpp b/src/hotspot/share/opto/regmask.cpp index 492c1479e5d..01bdbec6769 100644 --- a/src/hotspot/share/opto/regmask.cpp +++ b/src/hotspot/share/opto/regmask.cpp @@ -319,8 +319,8 @@ bool RegMask::is_bound_set(const unsigned int size) const { if ((all & ~(bit-1)) != _RM_UP[i]) return false; // Found many bits, so fail i++; // Skip iteration forward and check high part - // The lower (BitsPerWord - size) bits should be 1 since it is split case. - uintptr_t set = (bit >> (BitsPerWord - bit_index)) - 1; + // The lower bits should be 1 since it is split case. + uintptr_t set = (bit >> (BitsPerWord - size)) - 1; if (i > _hwm || _RM_UP[i] != set) return false; // Require expected low bits in next word } diff --git a/src/hotspot/share/opto/vector.cpp b/src/hotspot/share/opto/vector.cpp index 943b15515e1..5ccf70c2228 100644 --- a/src/hotspot/share/opto/vector.cpp +++ b/src/hotspot/share/opto/vector.cpp @@ -219,12 +219,19 @@ void PhaseVector::scalarize_vbox_node(VectorBoxNode* vec_box) { // Process debug uses at safepoints Unique_Node_List safepoints(C->comp_arena()); - for (DUIterator_Fast imax, i = vec_box->fast_outs(imax); i < imax; i++) { - Node* use = vec_box->fast_out(i); - if (use->is_SafePoint()) { - SafePointNode* sfpt = use->as_SafePoint(); - if (!sfpt->is_Call() || !sfpt->as_Call()->has_non_debug_use(vec_box)) { - safepoints.push(sfpt); + Unique_Node_List worklist(C->comp_arena()); + worklist.push(vec_box); + while (worklist.size() > 0) { + Node* n = worklist.pop(); + for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { + Node* use = n->fast_out(i); + if (use->is_SafePoint()) { + SafePointNode* sfpt = use->as_SafePoint(); + if (!sfpt->is_Call() || !sfpt->as_Call()->has_non_debug_use(n)) { + safepoints.push(sfpt); + } + } else if (use->is_ConstraintCast()) { + worklist.push(use); // reversed version of Node::uncast() } } } @@ -251,11 +258,13 @@ void PhaseVector::scalarize_vbox_node(VectorBoxNode* vec_box) { jvms->set_endoff(sfpt->req()); // Now make a pass over the debug information replacing any references - // to the allocated object with "sobj" - int start = jvms->debug_start(); - int end = jvms->debug_end(); - sfpt->replace_edges_in_range(vec_box, sobj, start, end); - + // to the allocated object with vector value. + for (uint i = jvms->debug_start(); i < jvms->debug_end(); i++) { + Node* debug = sfpt->in(i); + if (debug != NULL && debug->uncast(/*keep_deps*/false) == vec_box) { + sfpt->set_req(i, sobj); + } + } C->record_for_igvn(sfpt); } } @@ -319,7 +328,7 @@ Node* PhaseVector::expand_vbox_alloc_node(VectorBoxAllocateNode* vbox_alloc, value = gvn.transform(VectorStoreMaskNode::make(gvn, value, bt, num_elem)); // Although type of mask depends on its definition, in terms of storage everything is stored in boolean array. bt = T_BOOLEAN; - assert(value->as_Vector()->bottom_type()->is_vect()->element_basic_type() == bt, + assert(value->bottom_type()->is_vect()->element_basic_type() == bt, "must be consistent with mask representation"); } @@ -380,7 +389,8 @@ void PhaseVector::expand_vunbox_node(VectorUnboxNode* vec_unbox) { Node* obj = vec_unbox->obj(); const TypeInstPtr* tinst = gvn.type(obj)->isa_instptr(); ciInstanceKlass* from_kls = tinst->klass()->as_instance_klass(); - BasicType bt = vec_unbox->vect_type()->element_basic_type(); + const TypeVect* vt = vec_unbox->bottom_type()->is_vect(); + BasicType bt = vt->element_basic_type(); BasicType masktype = bt; BasicType elem_bt; @@ -419,7 +429,6 @@ void PhaseVector::expand_vunbox_node(VectorUnboxNode* vec_unbox) { Node* adr = kit.array_element_address(vec_field_ld, gvn.intcon(0), bt); const TypePtr* adr_type = adr->bottom_type()->is_ptr(); - const TypeVect* vt = vec_unbox->bottom_type()->is_vect(); int num_elem = vt->length(); Node* vec_val_load = LoadVectorNode::make(0, ctrl, @@ -432,14 +441,13 @@ void PhaseVector::expand_vunbox_node(VectorUnboxNode* vec_unbox) { C->set_max_vector_size(MAX2(C->max_vector_size(), vt->length_in_bytes())); - if (is_vector_mask(from_kls) && masktype != T_BOOLEAN) { - assert(vec_unbox->bottom_type()->is_vect()->element_basic_type() == masktype, "expect mask type consistency"); + if (is_vector_mask(from_kls)) { vec_val_load = gvn.transform(new VectorLoadMaskNode(vec_val_load, TypeVect::make(masktype, num_elem))); } else if (is_vector_shuffle(from_kls)) { if (vec_unbox->is_shuffle_to_vector() == false) { assert(vec_unbox->bottom_type()->is_vect()->element_basic_type() == masktype, "expect shuffle type consistency"); vec_val_load = gvn.transform(new VectorLoadShuffleNode(vec_val_load, TypeVect::make(masktype, num_elem))); - } else if (elem_bt != T_BYTE) { + } else { vec_val_load = gvn.transform(VectorCastNode::make(Op_VectorCastB2X, vec_val_load, elem_bt, num_elem)); } } diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index 4cbf2cd8662..872701105dd 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -1010,6 +1010,24 @@ ReductionNode* ReductionNode::make(int opc, Node *ctrl, Node* n1, Node* n2, Basi } } +Node* VectorLoadMaskNode::Identity(PhaseGVN* phase) { + BasicType out_bt = type()->is_vect()->element_basic_type(); + if (out_bt == T_BOOLEAN) { + return in(1); // redundant conversion + } + return this; +} + +Node* VectorStoreMaskNode::Identity(PhaseGVN* phase) { + // Identity transformation on boolean vectors. + // VectorStoreMask (VectorLoadMask bv) elem_size ==> bv + // vector[n]{bool} => vector[n]{t} => vector[n]{bool} + if (in(1)->Opcode() == Op_VectorLoadMask) { + return in(1)->in(1); + } + return this; +} + VectorStoreMaskNode* VectorStoreMaskNode::make(PhaseGVN& gvn, Node* in, BasicType in_type, uint num_elem) { assert(in->bottom_type()->isa_vect(), "sanity"); const TypeVect* vt = TypeVect::make(T_BOOLEAN, num_elem); @@ -1046,6 +1064,17 @@ int VectorCastNode::opcode(BasicType bt) { } } +Node* VectorCastNode::Identity(PhaseGVN* phase) { + if (!in(1)->is_top()) { + BasicType in_bt = in(1)->bottom_type()->is_vect()->element_basic_type(); + BasicType out_bt = vect_type()->element_basic_type(); + if (in_bt == out_bt) { + return in(1); // redundant cast + } + } + return this; +} + Node* ReductionNode::make_reduction_input(PhaseGVN& gvn, int opc, BasicType bt) { int vopc = opcode(opc, bt); guarantee(vopc != opc, "Vector reduction for '%s' is not implemented", NodeClassNames[opc]); @@ -1219,11 +1248,48 @@ Node* VectorInsertNode::make(Node* vec, Node* new_val, int position) { return new VectorInsertNode(vec, new_val, pos, vec->bottom_type()->is_vect()); } -Node* VectorUnboxNode::Identity(PhaseGVN *phase) { +Node* VectorUnboxNode::Ideal(PhaseGVN* phase, bool can_reshape) { + Node* n = obj()->uncast(); + if (EnableVectorReboxing && n->Opcode() == Op_VectorBox) { + if (Type::cmp(bottom_type(), n->in(VectorBoxNode::Value)->bottom_type()) == 0) { + // Handled by VectorUnboxNode::Identity() + } else { + VectorBoxNode* vbox = static_cast(n); + ciKlass* vbox_klass = vbox->box_type()->klass(); + const TypeVect* in_vt = vbox->vec_type(); + const TypeVect* out_vt = type()->is_vect(); + assert(in_vt->length() == out_vt->length(), "mismatch on number of elements"); + Node* value = vbox->in(VectorBoxNode::Value); + + bool is_vector_mask = vbox_klass->is_subclass_of(ciEnv::current()->vector_VectorMask_klass()); + bool is_vector_shuffle = vbox_klass->is_subclass_of(ciEnv::current()->vector_VectorShuffle_klass()); + if (is_vector_mask) { + // VectorUnbox (VectorBox vmask) ==> VectorLoadMask (VectorStoreMask vmask) + value = phase->transform(VectorStoreMaskNode::make(*phase, value, in_vt->element_basic_type(), in_vt->length())); + return new VectorLoadMaskNode(value, out_vt); + } else if (is_vector_shuffle) { + if (is_shuffle_to_vector()) { + // VectorUnbox (VectorBox vshuffle) ==> VectorCastB2X vshuffle + return new VectorCastB2XNode(value, out_vt); + } else { + // VectorUnbox (VectorBox vshuffle) ==> VectorLoadShuffle vshuffle + return new VectorLoadShuffleNode(value, out_vt); + } + } else { + assert(false, "type mismatch on vector: %s", vbox_klass->name()->as_utf8()); + } + } + } + return NULL; +} + +Node* VectorUnboxNode::Identity(PhaseGVN* phase) { Node* n = obj()->uncast(); if (EnableVectorReboxing && n->Opcode() == Op_VectorBox) { if (Type::cmp(bottom_type(), n->in(VectorBoxNode::Value)->bottom_type()) == 0) { - return n->in(VectorBoxNode::Value); + return n->in(VectorBoxNode::Value); // VectorUnbox (VectorBox v) ==> v + } else { + // Handled by VectorUnboxNode::Ideal(). } } return this; diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index a782b15cfa8..d4b2fc83079 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -1144,13 +1144,8 @@ class VectorTestNode : public Node { uint size_of() const { return sizeof(*this); } public: - VectorTestNode( Node *in1, Node *in2, BoolTest::mask predicate) : Node(NULL, in1, in2), _predicate(predicate) { - assert(in1->is_Vector() || in1->is_LoadVector(), "must be vector"); - assert(in2->is_Vector() || in2->is_LoadVector(), "must be vector"); - assert(in1->bottom_type()->is_vect()->element_basic_type() == in2->bottom_type()->is_vect()->element_basic_type(), - "same type elements are needed"); - assert(in1->bottom_type()->is_vect()->length() == in2->bottom_type()->is_vect()->length(), - "same number of elements is needed"); + VectorTestNode(Node* in1, Node* in2, BoolTest::mask predicate) : Node(NULL, in1, in2), _predicate(predicate) { + assert(in2->bottom_type()->is_vect() == in2->bottom_type()->is_vect(), "same vector type"); } virtual int Opcode() const; virtual uint hash() const { return Node::hash() + _predicate; } @@ -1188,37 +1183,34 @@ class VectorRearrangeNode : public VectorNode { Node* vec_shuffle() const { return in(2); } }; - -class VectorLoadMaskNode : public VectorNode { +class VectorLoadShuffleNode : public VectorNode { public: - VectorLoadMaskNode(Node* in, const TypeVect* vt) + VectorLoadShuffleNode(Node* in, const TypeVect* vt) : VectorNode(in, vt) { - assert(in->is_LoadVector(), "expected load vector"); - assert(in->as_LoadVector()->vect_type()->element_basic_type() == T_BOOLEAN, "must be boolean"); + assert(in->bottom_type()->is_vect()->element_basic_type() == T_BYTE, "must be BYTE"); } + int GetOutShuffleSize() const { return type2aelembytes(vect_type()->element_basic_type()); } virtual int Opcode() const; }; -class VectorLoadShuffleNode : public VectorNode { +class VectorLoadMaskNode : public VectorNode { public: - VectorLoadShuffleNode(Node* in, const TypeVect* vt) - : VectorNode(in, vt) { - assert(in->is_LoadVector(), "expected load vector"); - assert(in->as_LoadVector()->vect_type()->element_basic_type() == T_BYTE, "must be BYTE"); + VectorLoadMaskNode(Node* in, const TypeVect* vt) : VectorNode(in, vt) { + assert(in->bottom_type()->is_vect()->element_basic_type() == T_BOOLEAN, "must be boolean"); } - int GetOutShuffleSize() const { return type2aelembytes(vect_type()->element_basic_type()); } virtual int Opcode() const; + virtual Node* Identity(PhaseGVN* phase); }; class VectorStoreMaskNode : public VectorNode { protected: - VectorStoreMaskNode(Node* in1, ConINode* in2, const TypeVect* vt) - : VectorNode(in1, in2, vt) { } + VectorStoreMaskNode(Node* in1, ConINode* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {} public: virtual int Opcode() const; + virtual Node* Identity(PhaseGVN* phase); static VectorStoreMaskNode* make(PhaseGVN& gvn, Node* in, BasicType in_type, uint num_elem); }; @@ -1237,7 +1229,7 @@ class VectorReinterpretNode : public VectorNode { virtual bool cmp( const Node &n ) const { return VectorNode::cmp(n) && !Type::cmp(_src_vt,((VectorReinterpretNode&)n)._src_vt); } - virtual Node *Identity(PhaseGVN *phase); + virtual Node* Identity(PhaseGVN* phase); virtual int Opcode() const; }; @@ -1250,6 +1242,8 @@ class VectorCastNode : public VectorNode { static VectorCastNode* make(int vopc, Node* n1, BasicType bt, uint vlen); static int opcode(BasicType bt); static bool implemented(BasicType bt, uint vlen); + + virtual Node* Identity(PhaseGVN* phase); }; class VectorCastB2XNode : public VectorCastNode { @@ -1370,7 +1364,8 @@ class VectorUnboxNode : public VectorNode { virtual int Opcode() const; Node* obj() const { return in(2); } Node* mem() const { return in(1); } - virtual Node *Identity(PhaseGVN *phase); + virtual Node* Identity(PhaseGVN* phase); + Node* Ideal(PhaseGVN* phase, bool can_reshape); bool is_shuffle_to_vector() { return _shuffle_to_vector; } }; diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 80d33a6e2da..7e780990401 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -299,7 +299,6 @@ static jint wb_stress_virtual_space_resize(size_t reserved_space_size, int seed = os::random(); tty->print_cr("Random seed is %d", seed); - os::init_random(seed); for (size_t i = 0; i < iterations; i++) { diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index c7b5367456f..095c22bb316 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -63,6 +63,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/jniHandles.inline.hpp" +#include "runtime/keepStackGCProcessed.hpp" #include "runtime/objectMonitor.inline.hpp" #include "runtime/safepointVerifiers.hpp" #include "runtime/sharedRuntime.hpp" @@ -1651,10 +1652,7 @@ void Deoptimization::revoke_for_object_deoptimization(JavaThread* deoptee_thread return; } GrowableArray* objects_to_revoke = new GrowableArray(); - if (deoptee_thread != thread) { - // Process stack of deoptee thread as we will access oops during object deoptimization. - StackWatermarkSet::start_processing(deoptee_thread, StackWatermarkKind::gc); - } + assert(KeepStackGCProcessedMark::stack_is_kept_gc_processed(deoptee_thread), "must be"); // Collect monitors but only those with eliminated locking. get_monitors_from_stack(objects_to_revoke, deoptee_thread, fr, map, true); diff --git a/src/hotspot/share/runtime/keepStackGCProcessed.cpp b/src/hotspot/share/runtime/keepStackGCProcessed.cpp index df851b9f1cc..12bc3299f97 100644 --- a/src/hotspot/share/runtime/keepStackGCProcessed.cpp +++ b/src/hotspot/share/runtime/keepStackGCProcessed.cpp @@ -58,3 +58,19 @@ KeepStackGCProcessedMark::~KeepStackGCProcessedMark() { void KeepStackGCProcessedMark::finish_processing() { StackWatermarkSet::finish_processing(_jt, NULL /* context */, StackWatermarkKind::gc); } + +#ifdef ASSERT +bool KeepStackGCProcessedMark::stack_is_kept_gc_processed(JavaThread* jt) { + if (!Thread::current()->is_Java_thread()) { + assert(SafepointSynchronize::is_at_safepoint() && Thread::current()->is_VM_thread(), + "must be either Java thread or VM thread in a safepoint"); + return true; + } + StackWatermark* our_watermark = StackWatermarkSet::get(JavaThread::current(), StackWatermarkKind::gc); + if (our_watermark == nullptr) { + return true; + } + StackWatermark* their_watermark = StackWatermarkSet::get(jt, StackWatermarkKind::gc); + return our_watermark->linked_watermark() == their_watermark; +} +#endif // ASSERT diff --git a/src/hotspot/share/runtime/keepStackGCProcessed.hpp b/src/hotspot/share/runtime/keepStackGCProcessed.hpp index 2c36991fe28..9ac12520ba1 100644 --- a/src/hotspot/share/runtime/keepStackGCProcessed.hpp +++ b/src/hotspot/share/runtime/keepStackGCProcessed.hpp @@ -43,6 +43,8 @@ class KeepStackGCProcessedMark : public StackObj { public: KeepStackGCProcessedMark(JavaThread* jt); ~KeepStackGCProcessedMark(); + + static bool stack_is_kept_gc_processed(JavaThread* jt) NOT_DEBUG({ return true; }) ; }; diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 3dbc225624a..4d702eb9469 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -72,7 +72,7 @@ OSThread* os::_starting_thread = NULL; address os::_polling_page = NULL; -volatile unsigned int os::_rand_seed = 1; +volatile unsigned int os::_rand_seed = 1234567; int os::_processor_count = 0; int os::_initial_active_processor_count = 0; size_t os::_page_sizes[os::page_sizes_max]; diff --git a/src/hotspot/share/runtime/stackWatermark.hpp b/src/hotspot/share/runtime/stackWatermark.hpp index 99bd9b9f405..3cf7ce59cd9 100644 --- a/src/hotspot/share/runtime/stackWatermark.hpp +++ b/src/hotspot/share/runtime/stackWatermark.hpp @@ -130,6 +130,7 @@ class StackWatermark : public CHeapObj { void set_next(StackWatermark* n) { _next = n; } void link_watermark(StackWatermark* watermark); + DEBUG_ONLY(StackWatermark* linked_watermark() const { return _linked_watermark; }) uintptr_t watermark(); uintptr_t last_processed(); diff --git a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java index 759848063cb..49bf751c2e8 100644 --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java @@ -157,8 +157,8 @@ int compareTo(AbstractStringBuilder another) { return 0; } - byte val1[] = value; - byte val2[] = another.value; + byte[] val1 = value; + byte[] val2 = another.value; int count1 = this.count; int count2 = another.count; @@ -734,7 +734,7 @@ public AbstractStringBuilder append(char[] str) { * if {@code offset < 0} or {@code len < 0} * or {@code offset+len > str.length} */ - public AbstractStringBuilder append(char str[], int offset, int len) { + public AbstractStringBuilder append(char[] str, int offset, int len) { int end = offset + len; checkRange(offset, end, str.length); ensureCapacityInternal(count + len); @@ -1238,9 +1238,6 @@ public AbstractStringBuilder insert(int dstOffset, CharSequence s) { if (s == null) { s = "null"; } - if (s instanceof String) { - return this.insert(dstOffset, (String)s); - } return this.insert(dstOffset, s, 0, s.length()); } @@ -1300,7 +1297,11 @@ public AbstractStringBuilder insert(int dstOffset, CharSequence s, ensureCapacityInternal(count + len); shift(dstOffset, len); count += len; - putCharsAt(dstOffset, s, start, end); + if (s instanceof String) { + putStringAt(dstOffset, (String) s, start, end); + } else { + putCharsAt(dstOffset, s, start, end); + } return this; } @@ -1558,9 +1559,8 @@ public int lastIndexOf(String str, int fromIndex) { public AbstractStringBuilder reverse() { byte[] val = this.value; int count = this.count; - int coder = this.coder; int n = count - 1; - if (COMPACT_STRINGS && coder == LATIN1) { + if (isLatin1()) { for (int j = (n-1) >> 1; j >= 0; j--) { int k = n - j; byte cj = val[j]; @@ -1648,7 +1648,7 @@ final byte[] getValue() { * @param dstBegin the char index, not offset of byte[] * @param coder the coder of dst[] */ - void getBytes(byte dst[], int dstBegin, byte coder) { + void getBytes(byte[] dst, int dstBegin, byte coder) { if (this.coder == coder) { System.arraycopy(value, 0, dst, dstBegin << coder, count << coder); } else { // this.coder == LATIN && coder == UTF16 @@ -1713,11 +1713,15 @@ private final void putCharsAt(int index, CharSequence s, int off, int end) { } } - private final void putStringAt(int index, String str) { + private void putStringAt(int index, String str, int off, int end) { if (getCoder() != str.coder()) { inflate(); } - str.getBytes(value, index, coder); + str.getBytes(value, off, index, coder, end); + } + + private void putStringAt(int index, String str) { + putStringAt(index, str, 0, str.length()); } private final void appendChars(char[] s, int off, int end) { diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index c186e797508..e96943ffe13 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -3599,7 +3599,7 @@ public String repeat(int count) { * @param dstBegin the char index, not offset of byte[] * @param coder the coder of dst[] */ - void getBytes(byte dst[], int dstBegin, byte coder) { + void getBytes(byte[] dst, int dstBegin, byte coder) { if (coder() == coder) { System.arraycopy(value, 0, dst, dstBegin << coder, value.length); } else { // this.coder == LATIN && coder == UTF16 @@ -3607,6 +3607,26 @@ void getBytes(byte dst[], int dstBegin, byte coder) { } } + /** + * Copy character bytes from this string into dst starting at dstBegin. + * This method doesn't perform any range checking. + * + * Invoker guarantees: dst is in UTF16 (inflate itself for asb), if two + * coders are different, and dst is big enough (range check) + * + * @param srcPos the char index, not offset of byte[] + * @param dstBegin the char index to start from + * @param coder the coder of dst[] + * @param length the amount of copied chars + */ + void getBytes(byte[] dst, int srcPos, int dstBegin, byte coder, int length) { + if (coder() == coder) { + System.arraycopy(value, srcPos, dst, dstBegin << coder, length << coder()); + } else { // this.coder == LATIN && coder == UTF16 + StringLatin1.inflate(value, srcPos, dst, dstBegin, length); + } + } + /* * Package private constructor. Trailing Void argument is there for * disambiguating it against other (public) constructors. diff --git a/src/java.base/share/classes/java/lang/invoke/BootstrapMethodInvoker.java b/src/java.base/share/classes/java/lang/invoke/BootstrapMethodInvoker.java index bd14bb81b05..44fa6101633 100644 --- a/src/java.base/share/classes/java/lang/invoke/BootstrapMethodInvoker.java +++ b/src/java.base/share/classes/java/lang/invoke/BootstrapMethodInvoker.java @@ -170,16 +170,7 @@ else if (info.getClass() == int[].class) { } } } - if (resultType.isPrimitive()) { - // Non-reference conversions are more than just plain casts. - // By pushing the value through a funnel of the form (T x)->x, - // the boxed result can be widened as needed. See MH::asType. - MethodHandle funnel = MethodHandles.identity(resultType); - result = funnel.invoke(result); - // Now it is the wrapper type for resultType. - resultType = Wrapper.asWrapperType(resultType); - } - return resultType.cast(result); + return widenAndCast(result, resultType); } catch (Error e) { // Pass through an Error, including BootstrapMethodError, any other @@ -195,6 +186,38 @@ else if (info.getClass() == int[].class) { } } + + /** + * If resultType is a reference type, do Class::cast on the result through + * an identity function of that type, as-type converted to return + * the corresponding reference wrapper type for resultType. + * Works like {@code MethodHandles.identity(resultType).invoke((Object)result)}. + * + * This utility function enforces type correctness of bootstrap method results. + * It is also used to enforce type correctness in other dependently-typed + * methods, such as classData. + */ + static T widenAndCast(Object result, Class resultType) throws Throwable { + if (!resultType.isPrimitive()) { + return resultType.cast(result); + } + + Class wrapperType = Wrapper.asWrapperType(resultType); + if (wrapperType.isInstance(result)) { + @SuppressWarnings("unchecked") + T wrapper = (T) result; + return wrapper; + } + // Non-reference conversions are more than just plain casts. + // By pushing the value through a funnel of the form (T x)->x, + // the boxed result can be widened as needed. See MH::asType. + // Note that this might widen byte into int, float into double, etc + MethodHandle funnel = MethodHandles.identity(resultType); + result = funnel.invoke(result); + // Now it is the wrapper type for resultType. + return wrapperType.cast(result); + } + // If we don't provide static type information for type, we'll generate runtime // checks. Let's try not to... diff --git a/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java b/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java index 71cae83e160..27d74284dc6 100644 --- a/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java +++ b/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java @@ -413,8 +413,8 @@ public static Object explicitCast(MethodHandles.Lookup lookup, String name, Clas MethodHandle conv = MethodHandles.explicitCastArguments(id, mt); try { return conv.invoke(value); - } catch (ClassCastException e) { - throw e; // specified, let CCE through + } catch (RuntimeException|Error e) { + throw e; // let specified CCE and other runtime exceptions/errors through } catch (Throwable throwable) { throw new InternalError(throwable); // Not specified, throw InternalError } diff --git a/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java b/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java index 5454eeca025..a6dbe6ef23f 100644 --- a/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java +++ b/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java @@ -34,6 +34,7 @@ import java.io.FilePermission; import java.io.Serializable; +import java.lang.constant.ConstantDescs; import java.lang.invoke.MethodHandles.Lookup; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; @@ -55,7 +56,7 @@ * @see LambdaMetafactory */ /* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory { - private static final int CLASSFILE_VERSION = 52; + private static final int CLASSFILE_VERSION = 59; private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE); private static final String JAVA_LANG_OBJECT = "java/lang/Object"; private static final String NAME_CTOR = ""; @@ -71,12 +72,10 @@ private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace"; private static final String NAME_METHOD_READ_OBJECT = "readObject"; private static final String NAME_METHOD_WRITE_OBJECT = "writeObject"; - private static final String NAME_FIELD_IMPL_METHOD = "protectedImplMethod"; private static final String DESCR_CLASS = "Ljava/lang/Class;"; private static final String DESCR_STRING = "Ljava/lang/String;"; private static final String DESCR_OBJECT = "Ljava/lang/Object;"; - private static final String DESCR_METHOD_HANDLE = "Ljava/lang/invoke/MethodHandle;"; private static final String DESCR_CTOR_SERIALIZED_LAMBDA = "(" + DESCR_CLASS + DESCR_STRING + DESCR_STRING + DESCR_STRING + "I" + DESCR_STRING + DESCR_STRING + DESCR_STRING + DESCR_STRING + "[" + DESCR_OBJECT + ")V"; @@ -94,6 +93,9 @@ private static final boolean disableEagerInitialization; + // condy to load implMethod from class data + private static final ConstantDynamic implMethodCondy; + static { final String dumpProxyClassesKey = "jdk.internal.lambda.dumpProxyClasses"; String dumpPath = GetPropertyAction.privilegedGetProperty(dumpProxyClassesKey); @@ -101,6 +103,12 @@ final String disableEagerInitializationKey = "jdk.internal.lambda.disableEagerInitialization"; disableEagerInitialization = GetBooleanAction.privilegedGetProperty(disableEagerInitializationKey); + + // condy to load implMethod from class data + MethodType classDataMType = MethodType.methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class); + Handle classDataBsm = new Handle(H_INVOKESTATIC, Type.getInternalName(MethodHandles.class), "classData", + classDataMType.descriptorString(), false); + implMethodCondy = new ConstantDynamic(ConstantDescs.DEFAULT_NAME, MethodHandle.class.descriptorString(), classDataBsm); } // See context values in AbstractValidatingLambdaMetafactory @@ -361,14 +369,6 @@ private Class generateInnerClass() throws LambdaConversionException { } } - if (useImplMethodHandle) { - FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_STATIC, - NAME_FIELD_IMPL_METHOD, - DESCR_METHOD_HANDLE, - null, null); - fv.visitEnd(); - } - if (isSerializable) generateSerializationFriendlyMethods(); else if (accidentallySerializable) @@ -394,7 +394,7 @@ public Void run() { } try { // this class is linked at the indy callsite; so define a hidden nestmate - Lookup lookup = caller.defineHiddenClass(classBytes, !disableEagerInitialization, NESTMATE, STRONG); + Lookup lookup; if (useImplMethodHandle) { // If the target class invokes a method reference this::m which is // resolved to a protected method inherited from a superclass in a different @@ -403,8 +403,10 @@ public Void run() { // This lambda proxy class has no access to the resolved method. // So this workaround by passing the live implMethod method handle // to the proxy class to invoke directly. - MethodHandle mh = lookup.findStaticSetter(lookup.lookupClass(), NAME_FIELD_IMPL_METHOD, MethodHandle.class); - mh.invokeExact(implMethod); + lookup = caller.defineHiddenClassWithClassData(classBytes, implMethod, !disableEagerInitialization, + NESTMATE, STRONG); + } else { + lookup = caller.defineHiddenClass(classBytes, !disableEagerInitialization, NESTMATE, STRONG); } return lookup.lookupClass(); } catch (IllegalAccessException e) { @@ -554,8 +556,7 @@ void generate(MethodType methodType) { visitInsn(DUP); } if (useImplMethodHandle) { - visitVarInsn(ALOAD, 0); - visitFieldInsn(GETSTATIC, lambdaClassName, NAME_FIELD_IMPL_METHOD, DESCR_METHOD_HANDLE); + visitLdcInsn(implMethodCondy); } for (int i = 0; i < argNames.length; i++) { visitVarInsn(ALOAD, 0); diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java index 8f4ccf65d5b..0112120e98e 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -35,6 +35,7 @@ import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandleStatics.TRACE_METHOD_LINKAGE; +import static java.lang.invoke.MethodHandleStatics.UNSAFE; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; /** @@ -683,10 +684,13 @@ static boolean canBeCalledVirtual(MemberName symbolicRef, Class definingClass private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); /* - * A convenient method for LambdaForms to get the class data of a given class. - * LambdaForms cannot use condy via MethodHandles.classData + * Returns the class data set by the VM in the Class::classData field. + * + * This is also invoked by LambdaForms as it cannot use condy via + * MethodHandles.classData due to bootstrapping issue. */ static Object classData(Class c) { + UNSAFE.ensureClassInitialized(c); return JLA.classData(c); } } diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index 7a615729c4e..80313f466e7 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -25,7 +25,6 @@ package java.lang.invoke; -import jdk.internal.access.JavaLangAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.misc.Unsafe; import jdk.internal.misc.VM; @@ -42,6 +41,7 @@ import sun.reflect.misc.ReflectUtil; import sun.security.util.SecurityConstants; +import java.lang.constant.ConstantDescs; import java.lang.invoke.LambdaForm.BasicType; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -101,13 +101,16 @@ private MethodHandles() { } // do not instantiate * direct method handles * for any member that the caller has access to via bytecodes, * including protected and private fields and methods. + * This lookup object is created by the original lookup class + * and has the {@link Lookup#ORIGINAL ORIGINAL} bit set. * This lookup object is a capability which may be delegated to trusted agents. * Do not store it in place where untrusted code can access it. *

* This method is caller sensitive, which means that it may return different * values to different callers. * @return a lookup object for the caller of this method, with - * {@linkplain Lookup#hasFullPrivilegeAccess() full privilege access} + * {@linkplain Lookup#ORIGINAL original} and + * {@linkplain Lookup#hasFullPrivilegeAccess() full privilege access}. */ @CallerSensitive @ForceInline // to ensure Reflection.getCallerClass optimization @@ -201,13 +204,15 @@ public static Lookup publicLookup() { *

* Otherwise, if {@code M1} and {@code M2} are the same module, this method * returns a {@code Lookup} on {@code targetClass} with - * {@linkplain Lookup#hasFullPrivilegeAccess() full privilege access} and - * {@code null} previous lookup class. + * {@linkplain Lookup#hasFullPrivilegeAccess() full privilege access} + * with {@code null} previous lookup class. *

* Otherwise, {@code M1} and {@code M2} are two different modules. This method * returns a {@code Lookup} on {@code targetClass} that records - * the lookup class of the caller as the new previous lookup class and - * drops {@code MODULE} access from the full privilege access. + * the lookup class of the caller as the new previous lookup class with + * {@code PRIVATE} access but no {@code MODULE} access. + *

+ * The resulting {@code Lookup} object has no {@code ORIGINAL} access. * * @param targetClass the target class * @param caller the caller lookup object @@ -232,7 +237,8 @@ public static Lookup privateLookupIn(Class targetClass, Lookup caller) throws if (targetClass.isArray()) throw new IllegalArgumentException(targetClass + " is an array class"); // Ensure that we can reason accurately about private and module access. - if (!caller.hasFullPrivilegeAccess()) + int requireAccess = Lookup.PRIVATE|Lookup.MODULE; + if ((caller.lookupModes() & requireAccess) != requireAccess) throw new IllegalAccessException("caller does not have PRIVATE and MODULE lookup mode"); // previous lookup class is never set if it has MODULE access @@ -242,7 +248,7 @@ public static Lookup privateLookupIn(Class targetClass, Lookup caller) throws Module callerModule = callerClass.getModule(); // M1 Module targetModule = targetClass.getModule(); // M2 Class newPreviousClass = null; - int newModes = Lookup.FULL_POWER_MODES; + int newModes = Lookup.FULL_POWER_MODES & ~Lookup.ORIGINAL; if (targetModule != callerModule) { if (!callerModule.canRead(targetModule)) @@ -270,53 +276,154 @@ public static Lookup privateLookupIn(Class targetClass, Lookup caller) throws /** * Returns the class data associated with the lookup class - * of the specified {@code Lookup} object, or {@code null}. + * of the given {@code caller} lookup object, or {@code null}. * - *

Classes can be created with class data by calling - * {@link Lookup#defineHiddenClassWithClassData(byte[], Object, Lookup.ClassOption...) + *

A hidden class with class data can be created by calling + * {@link Lookup#defineHiddenClassWithClassData(byte[], Object, boolean, Lookup.ClassOption...) * Lookup::defineHiddenClassWithClassData}. - * A hidden class with a class data behaves as if the hidden class - * has a private static final unnamed field pre-initialized with - * the class data and this method is equivalent as if calling - * {@link ConstantBootstraps#getStaticFinal(Lookup, String, Class)} to - * obtain the value of such field corresponding to the class data. + * This method will cause the static class initializer of the lookup + * class of the given {@code caller} lookup object be executed if + * it has not been initialized. + * + *

A hidden class created by {@link Lookup#defineHiddenClass(byte[], boolean, Lookup.ClassOption...) + * Lookup::defineHiddenClass} and non-hidden classes have no class data. + * {@code null} is returned if this method is called on the lookup object + * on these classes. * *

The {@linkplain Lookup#lookupModes() lookup modes} for this lookup - * must have {@link Lookup#ORIGINAL ORIGINAL} access in order to retrieve - * the class data. + * must have {@linkplain Lookup#ORIGINAL original access} + * in order to retrieve the class data. * * @apiNote * This method can be called as a bootstrap method for a dynamically computed * constant. A framework can create a hidden class with class data, for - * example that can be {@code List.of(o1, o2, o3....)} containing more than - * one live object. The class data is accessible only to the lookup object + * example that can be {@code Class} or {@code MethodHandle} object. + * The class data is accessible only to the lookup object * created by the original caller but inaccessible to other members - * in the same nest. If a framework passes security sensitive live objects + * in the same nest. If a framework passes security sensitive objects * to a hidden class via class data, it is recommended to load the value * of class data as a dynamically computed constant instead of storing - * the live objects in private fields which are accessible to other - * nestmates. + * the class data in private static field(s) which are accessible to + * other nestmates. * * @param the type to cast the class data object to * @param caller the lookup context describing the class performing the * operation (normally stacked by the JVM) - * @param name ignored + * @param name must be {@link ConstantDescs#DEFAULT_NAME} + * ({@code "_"}) * @param type the type of the class data * @return the value of the class data if present in the lookup class; * otherwise {@code null} + * @throws IllegalArgumentException if name is not {@code "_"} * @throws IllegalAccessException if the lookup context does not have - * original caller access + * {@linkplain Lookup#ORIGINAL original} access * @throws ClassCastException if the class data cannot be converted to - * the specified {@code type} - * @see Lookup#defineHiddenClassWithClassData(byte[], Object, Lookup.ClassOption...) - * @since 15 + * the given {@code type} + * @throws NullPointerException if {@code caller} or {@code type} argument + * is {@code null} + * @see Lookup#defineHiddenClassWithClassData(byte[], Object, boolean, Lookup.ClassOption...) + * @see MethodHandles#classDataAt(Lookup, String, Class, int) + * @since 16 + * @jvms 5.5 Initialization */ - static T classData(Lookup caller, String name, Class type) throws IllegalAccessException { - if (!caller.hasFullPrivilegeAccess()) { - throw new IllegalAccessException(caller + " does not have full privilege access"); + public static T classData(Lookup caller, String name, Class type) throws IllegalAccessException { + Objects.requireNonNull(caller); + Objects.requireNonNull(type); + if (!ConstantDescs.DEFAULT_NAME.equals(name)) { + throw new IllegalArgumentException("name must be \"_\": " + name); + } + + if ((caller.lookupModes() & Lookup.ORIGINAL) != Lookup.ORIGINAL) { + throw new IllegalAccessException(caller + " does not have ORIGINAL access"); + } + + Object classdata = MethodHandleNatives.classData(caller.lookupClass()); + if (classdata == null) return null; + + try { + return BootstrapMethodInvoker.widenAndCast(classdata, type); + } catch (RuntimeException|Error e) { + throw e; // let CCE and other runtime exceptions through + } catch (Throwable e) { + throw new InternalError(e); + } + } + + /** + * Returns the element at the specified index in the + * {@linkplain #classData(Lookup, String, Class) class data}, + * if the class data associated with the lookup class + * of the given {@code caller} lookup object is a {@code List}. + * If the class data is not present in this lookup class, this method + * returns {@code null}. + * + *

A hidden class with class data can be created by calling + * {@link Lookup#defineHiddenClassWithClassData(byte[], Object, boolean, Lookup.ClassOption...) + * Lookup::defineHiddenClassWithClassData}. + * This method will cause the static class initializer of the lookup + * class of the given {@code caller} lookup object be executed if + * it has not been initialized. + * + *

A hidden class created by {@link Lookup#defineHiddenClass(byte[], boolean, Lookup.ClassOption...) + * Lookup::defineHiddenClass} and non-hidden classes have no class data. + * {@code null} is returned if this method is called on the lookup object + * on these classes. + * + *

The {@linkplain Lookup#lookupModes() lookup modes} for this lookup + * must have {@linkplain Lookup#ORIGINAL original access} + * in order to retrieve the class data. + * + * @apiNote + * This method can be called as a bootstrap method for a dynamically computed + * constant. A framework can create a hidden class with class data, for + * example that can be {@code List.of(o1, o2, o3....)} containing more than + * one object and use this method to load one element at a specific index. + * The class data is accessible only to the lookup object + * created by the original caller but inaccessible to other members + * in the same nest. If a framework passes security sensitive objects + * to a hidden class via class data, it is recommended to load the value + * of class data as a dynamically computed constant instead of storing + * the class data in private static field(s) which are accessible to other + * nestmates. + * + * @param the type to cast the result object to + * @param caller the lookup context describing the class performing the + * operation (normally stacked by the JVM) + * @param name must be {@link java.lang.constant.ConstantDescs#DEFAULT_NAME} + * ({@code "_"}) + * @param type the type of the element at the given index in the class data + * @param index index of the element in the class data + * @return the element at the given index in the class data + * if the class data is present; otherwise {@code null} + * @throws IllegalArgumentException if name is not {@code "_"} + * @throws IllegalAccessException if the lookup context does not have + * {@linkplain Lookup#ORIGINAL original} access + * @throws ClassCastException if the class data cannot be converted to {@code List} + * or the element at the specified index cannot be converted to the given type + * @throws IndexOutOfBoundsException if the index is out of range + * @throws NullPointerException if {@code caller} or {@code type} argument is + * {@code null}; or if unboxing operation fails because + * the element at the given index is {@code null} + * + * @since 16 + * @see #classData(Lookup, String, Class) + * @see Lookup#defineHiddenClassWithClassData(byte[], Object, boolean, Lookup.ClassOption...) + */ + public static T classDataAt(Lookup caller, String name, Class type, int index) + throws IllegalAccessException + { + @SuppressWarnings("unchecked") + List classdata = (List)classData(caller, name, List.class); + if (classdata == null) return null; + + try { + Object element = classdata.get(index); + return BootstrapMethodInvoker.widenAndCast(element, type); + } catch (RuntimeException|Error e) { + throw e; // let specified exceptions and other runtime exceptions/errors through + } catch (Throwable e) { + throw new InternalError(e); } - Object classData = MethodHandleNatives.classData(caller.lookupClass); - return type.cast(classData); } /** @@ -636,11 +743,17 @@ public static T reflectAs(Class expected, MethodHandle tar *

* Private and module access are independently determined modes; a lookup may have * either or both or neither. A lookup which possesses both access modes is said to - * possess {@linkplain #hasFullPrivilegeAccess() full privilege access}. Such a lookup has - * the following additional capability: + * possess {@linkplain #hasFullPrivilegeAccess() full privilege access}. + *

+ * A lookup with original access ensures that this lookup is created by + * the original lookup class and the bootstrap method invoked by the VM. + * Such a lookup with original access also has private and module access + * which has the following additional capability: *

    *
  • create method handles which invoke caller sensitive methods, * such as {@code Class.forName} + *
  • obtain the {@linkplain MethodHandles#classData(Lookup, String, Class) + * class data} associated with the lookup class
  • *
*

* Each of these permissions is a consequence of the fact that a lookup object @@ -811,6 +924,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * Lookup object + * original * protected * private * package @@ -821,6 +935,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * {@code CL = MethodHandles.lookup()} in {@code C} + * ORI * PRO * PRI * PAC @@ -831,6 +946,7 @@ public static T reflectAs(Class expected, MethodHandle tar * {@code CL.in(C1)} same package * * + * * PAC * MOD * 1R @@ -840,6 +956,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * MOD * 1R * @@ -849,6 +966,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * 2R * * @@ -857,10 +975,12 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * 2R * * * {@code PRI1 = privateLookupIn(C1,CL)} + * * PRO * PRI * PAC @@ -869,6 +989,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * {@code PRI1a = privateLookupIn(C,PRI1)} + * * PRO * PRI * PAC @@ -879,6 +1000,7 @@ public static T reflectAs(Class expected, MethodHandle tar * {@code PRI1.in(C1)} same package * * + * * PAC * MOD * 1R @@ -888,6 +1010,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * MOD * 1R * @@ -897,11 +1020,13 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * 2R * * * {@code PRI1.dropLookupMode(PROTECTED)} * + * * PRI * PAC * MOD @@ -911,6 +1036,7 @@ public static T reflectAs(Class expected, MethodHandle tar * {@code PRI1.dropLookupMode(PRIVATE)} * * + * * PAC * MOD * 1R @@ -920,6 +1046,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * MOD * 1R * @@ -929,6 +1056,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * 1R * * @@ -937,9 +1065,11 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * none * * {@code PRI2 = privateLookupIn(D,CL)} + * * PRO * PRI * PAC @@ -948,6 +1078,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * {@code privateLookupIn(D,PRI1)} + * * PRO * PRI * PAC @@ -960,12 +1091,14 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * IAE * * * {@code PRI2.in(D2)} same package * * + * * PAC * * 2R @@ -976,6 +1109,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * 2R * * @@ -984,6 +1118,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * 2R * * @@ -992,11 +1127,13 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * none * * * {@code PRI2.dropLookupMode(PROTECTED)} * + * * PRI * PAC * @@ -1006,6 +1143,7 @@ public static T reflectAs(Class expected, MethodHandle tar * {@code PRI2.dropLookupMode(PRIVATE)} * * + * * PAC * * 2R @@ -1016,6 +1154,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * 2R * * @@ -1024,6 +1163,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * 2R * * @@ -1032,11 +1172,13 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * none * * * {@code CL.dropLookupMode(PROTECTED)} * + * * PRI * PAC * MOD @@ -1046,6 +1188,7 @@ public static T reflectAs(Class expected, MethodHandle tar * {@code CL.dropLookupMode(PRIVATE)} * * + * * PAC * MOD * 1R @@ -1055,6 +1198,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * MOD * 1R * @@ -1064,6 +1208,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * 1R * * @@ -1072,6 +1217,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * none * * @@ -1080,6 +1226,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * U * * @@ -1088,6 +1235,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * U * * @@ -1096,6 +1244,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * U * * @@ -1104,6 +1253,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * none * * @@ -1112,6 +1262,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * IAE * * @@ -1120,6 +1271,7 @@ public static T reflectAs(Class expected, MethodHandle tar * * * + * * none * * @@ -1132,7 +1284,8 @@ public static T reflectAs(Class expected, MethodHandle tar * but {@code D} and {@code D2} are in module {@code M2}, and {@code E} * is in module {@code M3}. {@code X} stands for class which is inaccessible * to the lookup. {@code ANY} stands for any of the example lookups. - *

  • {@code PRO} indicates {@link #PROTECTED} bit set, + *
  • {@code ORI} indicates {@link #ORIGINAL} bit set, + * {@code PRO} indicates {@link #PROTECTED} bit set, * {@code PRI} indicates {@link #PRIVATE} bit set, * {@code PAC} indicates {@link #PACKAGE} bit set, * {@code MOD} indicates {@link #MODULE} bit set, @@ -1217,7 +1370,10 @@ public static T reflectAs(Class expected, MethodHandle tar *

    * If a security manager is present and the current lookup object does not have * {@linkplain #hasFullPrivilegeAccess() full privilege access}, then - * {@link #defineClass(byte[]) defineClass} + * {@link #defineClass(byte[]) defineClass}, + * {@link #defineHiddenClass(byte[], boolean, ClassOption...) defineHiddenClass}, + * {@link #defineHiddenClassWithClassData(byte[], Object, boolean, ClassOption...) + * defineHiddenClassWithClassData} * calls {@link SecurityManager#checkPermission smgr.checkPermission} * with {@code RuntimePermission("defineClass")}. * @@ -1240,7 +1396,7 @@ public static T reflectAs(Class expected, MethodHandle tar * In cases where the lookup object is * {@link MethodHandles#publicLookup() publicLookup()}, * or some other lookup object without the - * {@linkplain #hasFullPrivilegeAccess() full privilege access}, + * {@linkplain #ORIGINAL original access}, * the lookup class is disregarded. * In such cases, no caller-sensitive method handle can be created, * access is forbidden, and the lookup fails with an @@ -1351,16 +1507,32 @@ class Lookup { */ public static final int UNCONDITIONAL = PACKAGE << 2; - private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE | MODULE | UNCONDITIONAL); - private static final int FULL_POWER_MODES = (ALL_MODES & ~UNCONDITIONAL); + /** A single-bit mask representing {@code original} access + * which may contribute to the result of {@link #lookupModes lookupModes}. + * The value is {@code 0x40}, which does not correspond meaningfully to + * any particular {@linkplain java.lang.reflect.Modifier modifier bit}. + * + *

    + * If this lookup mode is set, the {@code Lookup} object must be + * created by the original lookup class by calling + * {@link MethodHandles#lookup()} method or by a bootstrap method + * invoked by the VM. The {@code Lookup} object with this lookup + * mode has {@linkplain #hasFullPrivilegeAccess() full privilege access}. + * + * @since 16 + */ + public static final int ORIGINAL = PACKAGE << 3; + + private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE | MODULE | UNCONDITIONAL | ORIGINAL); + private static final int FULL_POWER_MODES = (ALL_MODES & ~UNCONDITIONAL); // with original access private static final int TRUSTED = -1; /* - * Adjust PUBLIC => PUBLIC|MODULE|UNCONDITIONAL + * Adjust PUBLIC => PUBLIC|MODULE|ORIGINAL|UNCONDITIONAL * Adjust 0 => PACKAGE */ private static int fixmods(int mods) { - mods &= (ALL_MODES - PACKAGE - MODULE - UNCONDITIONAL); + mods &= (ALL_MODES - PACKAGE - MODULE - ORIGINAL - UNCONDITIONAL); if (Modifier.isPublic(mods)) mods |= UNCONDITIONAL; return (mods != 0) ? mods : PACKAGE; @@ -1416,7 +1588,8 @@ private Class lookupClassOrNull() { * {@linkplain #PROTECTED PROTECTED (0x04)}, * {@linkplain #PACKAGE PACKAGE (0x08)}, * {@linkplain #MODULE MODULE (0x10)}, - * and {@linkplain #UNCONDITIONAL UNCONDITIONAL (0x20)}. + * {@linkplain #UNCONDITIONAL UNCONDITIONAL (0x20)}, + * and {@linkplain #ORIGINAL ORIGINAL (0x40)}. *

    * A freshly-created lookup object * on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class} has @@ -1473,6 +1646,8 @@ private static Lookup newLookup(Class lookupClass, Class prevLookupClass, * However, the resulting {@code Lookup} object is guaranteed * to have no more access capabilities than the original. * In particular, access capabilities can be lost as follows:

      + *
    • If the new lookup class is different from the old lookup class, + * i.e. {@link #ORIGINAL ORIGINAL} access is lost. *
    • If the new lookup class is in a different module from the old one, * i.e. {@link #MODULE MODULE} access is lost. *
    • If the new lookup class is in a different package @@ -1528,7 +1703,7 @@ public Lookup in(Class requestedLookupClass) { return new Lookup(requestedLookupClass, null, FULL_POWER_MODES); if (requestedLookupClass == this.lookupClass) return this; // keep same capabilities - int newModes = (allowedModes & FULL_POWER_MODES); + int newModes = (allowedModes & FULL_POWER_MODES) & ~ORIGINAL; Module fromModule = this.lookupClass.getModule(); Module targetModule = requestedLookupClass.getModule(); Class plc = this.previousLookupClass(); @@ -1569,7 +1744,8 @@ public Lookup in(Class requestedLookupClass) { * finds members, but with a lookup mode that has lost the given lookup mode. * The lookup mode to drop is one of {@link #PUBLIC PUBLIC}, {@link #MODULE * MODULE}, {@link #PACKAGE PACKAGE}, {@link #PROTECTED PROTECTED}, - * {@link #PRIVATE PRIVATE}, or {@link #UNCONDITIONAL UNCONDITIONAL}. + * {@link #PRIVATE PRIVATE}, {@link #ORIGINAL ORIGINAL}, or + * {@link #UNCONDITIONAL UNCONDITIONAL}. * *

      If this lookup is a {@linkplain MethodHandles#publicLookup() public lookup}, * this lookup has {@code UNCONDITIONAL} mode set and it has no other mode set. @@ -1578,8 +1754,9 @@ public Lookup in(Class requestedLookupClass) { * *

      If this lookup is not a public lookup, then the following applies * regardless of its {@linkplain #lookupModes() lookup modes}. - * {@link #PROTECTED PROTECTED} is always dropped and so the resulting lookup - * mode will never have this access capability. When dropping {@code PACKAGE} + * {@link #PROTECTED PROTECTED} and {@link #ORIGINAL ORIGINAL} are always + * dropped and so the resulting lookup mode will never have these access + * capabilities. When dropping {@code PACKAGE} * then the resulting lookup will not have {@code PACKAGE} or {@code PRIVATE} * access. When dropping {@code MODULE} then the resulting lookup will not * have {@code MODULE}, {@code PACKAGE}, or {@code PRIVATE} access. @@ -1600,19 +1777,21 @@ public Lookup in(Class requestedLookupClass) { * @param modeToDrop the lookup mode to drop * @return a lookup object which lacks the indicated mode, or the same object if there is no change * @throws IllegalArgumentException if {@code modeToDrop} is not one of {@code PUBLIC}, - * {@code MODULE}, {@code PACKAGE}, {@code PROTECTED}, {@code PRIVATE} or {@code UNCONDITIONAL} + * {@code MODULE}, {@code PACKAGE}, {@code PROTECTED}, {@code PRIVATE}, {@code ORIGINAL} + * or {@code UNCONDITIONAL} * @see MethodHandles#privateLookupIn * @since 9 */ public Lookup dropLookupMode(int modeToDrop) { int oldModes = lookupModes(); - int newModes = oldModes & ~(modeToDrop | PROTECTED); + int newModes = oldModes & ~(modeToDrop | PROTECTED | ORIGINAL); switch (modeToDrop) { case PUBLIC: newModes &= ~(FULL_POWER_MODES); break; case MODULE: newModes &= ~(PACKAGE | PRIVATE); break; case PACKAGE: newModes &= ~(PRIVATE); break; case PROTECTED: case PRIVATE: + case ORIGINAL: case UNCONDITIONAL: break; default: throw new IllegalArgumentException(modeToDrop + " is not a valid mode to drop"); } @@ -1905,7 +2084,9 @@ static int optionsToFlag(Set options) { * The Java Virtual Machine Specification. * @param initialize if {@code true} the class will be initialized. * @param options {@linkplain ClassOption class options} - * @return the {@code Lookup} object on the hidden class + * @return the {@code Lookup} object on the hidden class, + * with {@linkplain #ORIGINAL original} and + * {@linkplain Lookup#hasFullPrivilegeAccess() full privilege} access * * @throws IllegalAccessException if this {@code Lookup} does not have * {@linkplain #hasFullPrivilegeAccess() full privilege} access @@ -1958,19 +2139,37 @@ public Lookup defineHiddenClass(byte[] bytes, boolean initialize, ClassOption... * returning a {@code Lookup} on the newly created class or interface. * *

      This method is equivalent to calling - * {@link #defineHiddenClass(byte[], boolean, ClassOption...) defineHiddenClass(bytes, true, options)} - * as if the hidden class has a private static final unnamed field whose value - * is initialized to {@code classData} right before the class initializer is - * executed. The newly created class is linked and initialized by the Java - * Virtual Machine. + * {@link #defineHiddenClass(byte[], boolean, ClassOption...) defineHiddenClass(bytes, initialize, options)} + * as if the hidden class is injected with a private static final unnamed + * field which is initialized with the given {@code classData} at + * the first instruction of the class initializer. + * The newly created class is linked by the Java Virtual Machine. * *

      The {@link MethodHandles#classData(Lookup, String, Class) MethodHandles::classData} - * method can be used to retrieve the {@code classData}. + * and {@link MethodHandles#classDataAt(Lookup, String, Class, int) MethodHandles::classDataAt} + * methods can be used to retrieve the {@code classData}. + * + * @apiNote + * A framework can create a hidden class with class data with one or more + * objects and load the class data as dynamically-computed constant(s) + * via a bootstrap method. {@link MethodHandles#classData(Lookup, String, Class) + * Class data} is accessible only to the lookup object created by the newly + * defined hidden class but inaccessible to other members in the same nest + * (unlike private static fields that are accessible to nestmates). + * Care should be taken w.r.t. mutability for example when passing + * an array or other mutable structure through the class data. + * Changing any value stored in the class data at runtime may lead to + * unpredictable behavior. + * If the class data is a {@code List}, it is good practice to make it + * unmodifiable for example via {@link List#of List::of}. * * @param bytes the class bytes * @param classData pre-initialized class data + * @param initialize if {@code true} the class will be initialized. * @param options {@linkplain ClassOption class options} - * @return the {@code Lookup} object on the hidden class + * @return the {@code Lookup} object on the hidden class, + * with {@linkplain #ORIGINAL original} and + * {@linkplain Lookup#hasFullPrivilegeAccess() full privilege} access * * @throws IllegalAccessException if this {@code Lookup} does not have * {@linkplain #hasFullPrivilegeAccess() full privilege} access @@ -1990,11 +2189,23 @@ public Lookup defineHiddenClass(byte[] bytes, boolean initialize, ClassOption... * @throws LinkageError if the newly created class cannot be linked for any other reason * @throws NullPointerException if any parameter is {@code null} * - * @since 15 + * @since 16 * @see Lookup#defineHiddenClass(byte[], boolean, ClassOption...) * @see Class#isHidden() + * @see MethodHandles#classData(Lookup, String, Class) + * @see MethodHandles#classDataAt(Lookup, String, Class, int) + * @jvms 4.2.1 Binary Class and Interface Names + * @jvms 4.2.2 Unqualified Names + * @jvms 4.7.28 The {@code NestHost} Attribute + * @jvms 4.7.29 The {@code NestMembers} Attribute + * @jvms 5.4.3.1 Class and Interface Resolution + * @jvms 5.4.4 Access Control + * @jvms 5.3.5 Deriving a {@code Class} from a {@code class} File Representation + * @jvms 5.4 Linking + * @jvms 5.5 Initialization + * @jls 12.7 Unloading of Classes and Interface */ - /* package-private */ Lookup defineHiddenClassWithClassData(byte[] bytes, Object classData, ClassOption... options) + public Lookup defineHiddenClassWithClassData(byte[] bytes, Object classData, boolean initialize, ClassOption... options) throws IllegalAccessException { Objects.requireNonNull(bytes); @@ -2007,7 +2218,7 @@ public Lookup defineHiddenClass(byte[] bytes, boolean initialize, ClassOption... } return makeHiddenClassDefiner(bytes.clone(), Set.of(options), false) - .defineClassAsLookup(true, classData); + .defineClassAsLookup(initialize, classData); } static class ClassFile { @@ -2238,8 +2449,6 @@ Class defineClass(boolean initialize, Object classData) { } Lookup defineClassAsLookup(boolean initialize, Object classData) { - // initialize must be true if classData is non-null - assert classData == null || initialize == true; Class c = defineClass(initialize, classData); return new Lookup(c, null, FULL_POWER_MODES); } @@ -2295,7 +2504,8 @@ private static void checkUnprivilegedlookupClass(Class lookupClass) { *

    • If public and package access are allowed, the suffix is "/package". *
    • If public, package, and private access are allowed, the suffix is "/private". *
    - * If none of the above cases apply, it is the case that full access + * If none of the above cases apply, it is the case that + * {@linkplain #hasFullPrivilegeAccess() full privilege access} * (public, module, package, private, and protected) is allowed. * In this case, no suffix is added. * This is true only of an object obtained originally from @@ -2329,12 +2539,13 @@ public String toString() { case PUBLIC|PACKAGE: case PUBLIC|MODULE|PACKAGE: return cname + "/package"; - case FULL_POWER_MODES & (~PROTECTED): - case FULL_POWER_MODES & ~(PROTECTED|MODULE): - return cname + "/private"; + case PUBLIC|PACKAGE|PRIVATE: + case PUBLIC|MODULE|PACKAGE|PRIVATE: + return cname + "/private"; + case PUBLIC|PACKAGE|PRIVATE|PROTECTED: + case PUBLIC|MODULE|PACKAGE|PRIVATE|PROTECTED: case FULL_POWER_MODES: - case FULL_POWER_MODES & (~MODULE): - return cname; + return cname; case TRUSTED: return "/trusted"; // internal only; not exported default: // Should not happen, but it's a bitfield... @@ -3415,7 +3626,7 @@ public MethodHandleInfo revealDirect(MethodHandle target) { } if (allowedModes != TRUSTED && member.isCallerSensitive()) { Class callerClass = target.internalCallerClass(); - if (!hasFullPrivilegeAccess() || callerClass != lookupClass()) + if ((lookupModes() & ORIGINAL) == 0 || callerClass != lookupClass()) throw new IllegalArgumentException("method handle is caller sensitive: "+callerClass); } // Produce the handle to the results. @@ -3480,11 +3691,11 @@ void checkMethodName(byte refKind, String name) throws NoSuchMethodException { /** * Find my trustable caller class if m is a caller sensitive method. - * If this lookup object has full privilege access, then the caller class is the lookupClass. + * If this lookup object has original full privilege access, then the caller class is the lookupClass. * Otherwise, if m is caller-sensitive, throw IllegalAccessException. */ Lookup findBoundCallerLookup(MemberName m) throws IllegalAccessException { - if (MethodHandleNatives.isCallerSensitive(m) && !hasFullPrivilegeAccess()) { + if (MethodHandleNatives.isCallerSensitive(m) && (lookupModes() & ORIGINAL) == 0) { // Only lookups with full privilege access are allowed to resolve caller-sensitive methods throw new IllegalAccessException("Attempt to lookup caller-sensitive method using restricted lookup object"); } @@ -3510,7 +3721,8 @@ public boolean hasPrivateAccess() { * Returns {@code true} if this lookup has full privilege access, * i.e. {@code PRIVATE} and {@code MODULE} access. * A {@code Lookup} object must have full privilege access in order to - * access all members that are allowed to the {@linkplain #lookupClass() lookup class}. + * access all members that are allowed to the + * {@linkplain #lookupClass() lookup class}. * * @return {@code true} if this lookup has full privilege access. * @since 14 @@ -3531,14 +3743,14 @@ void checkSecurityManager(Class refc) { if (smgr == null) return; // Step 1: - boolean fullPowerLookup = hasFullPrivilegeAccess(); - if (!fullPowerLookup || + boolean fullPrivilegeLookup = hasFullPrivilegeAccess(); + if (!fullPrivilegeLookup || !VerifyAccess.classLoaderIsAncestor(lookupClass, refc)) { ReflectUtil.checkPackageAccess(refc); } // Step 2b: - if (!fullPowerLookup) { + if (!fullPrivilegeLookup) { smgr.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); } } @@ -3546,7 +3758,11 @@ void checkSecurityManager(Class refc) { /** * Perform steps 1, 2a and 3 access checks. * Determines a trustable caller class to compare with refc, the symbolic reference class. - * If this lookup object has full privilege access, then the caller class is the lookupClass. + * If this lookup object has full privilege access except original access, + * then the caller class is the lookupClass. + * + * Lookup object created by {@link MethodHandles#privateLookupIn(Class, Lookup)} + * from the same module skips the security permission check. */ void checkSecurityManager(Class refc, MemberName m) { Objects.requireNonNull(refc); @@ -3558,21 +3774,21 @@ void checkSecurityManager(Class refc, MemberName m) { if (smgr == null) return; // Step 1: - boolean fullPowerLookup = hasFullPrivilegeAccess(); - if (!fullPowerLookup || + boolean fullPrivilegeLookup = hasFullPrivilegeAccess(); + if (!fullPrivilegeLookup || !VerifyAccess.classLoaderIsAncestor(lookupClass, refc)) { ReflectUtil.checkPackageAccess(refc); } // Step 2a: if (m.isPublic()) return; - if (!fullPowerLookup) { + if (!fullPrivilegeLookup) { smgr.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); } // Step 3: Class defc = m.getDeclaringClass(); - if (!fullPowerLookup && defc != refc) { + if (!fullPrivilegeLookup && defc != refc) { ReflectUtil.checkPackageAccess(defc); } } @@ -3787,9 +4003,11 @@ private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh, Lookup // boundCaller must have full privilege access. // It should have been checked by findBoundCallerLookup. Safe to check this again. - if (!boundCaller.hasFullPrivilegeAccess()) + if ((boundCaller.lookupModes() & ORIGINAL) == 0) throw new IllegalAccessException("Attempt to lookup caller-sensitive method using restricted lookup object"); + assert boundCaller.hasFullPrivilegeAccess(); + MethodHandle cbmh = MethodHandleImpl.bindCaller(mh, boundCaller.lookupClass); // Note: caller will apply varargs after this step happens. return cbmh; diff --git a/src/java.base/share/classes/java/util/ImmutableCollections.java b/src/java.base/share/classes/java/util/ImmutableCollections.java index 63fdebee948..4c651250f2e 100644 --- a/src/java.base/share/classes/java/util/ImmutableCollections.java +++ b/src/java.base/share/classes/java/util/ImmutableCollections.java @@ -93,26 +93,27 @@ class ImmutableCollections { private static Object[] archivedObjects; private static final Object EMPTY; - static final ListN EMPTY_LIST; - + static final ListN EMPTY_LIST_NULLS; static final SetN EMPTY_SET; - static final MapN EMPTY_MAP; static { CDS.initializeFromArchive(ImmutableCollections.class); if (archivedObjects == null) { EMPTY = new Object(); - EMPTY_LIST = new ListN<>(new Object[0]); + EMPTY_LIST = new ListN<>(new Object[0], false); + EMPTY_LIST_NULLS = new ListN<>(new Object[0], true); EMPTY_SET = new SetN<>(); EMPTY_MAP = new MapN<>(); - archivedObjects = new Object[] { EMPTY, EMPTY_LIST, EMPTY_SET, EMPTY_MAP }; + archivedObjects = + new Object[] { EMPTY, EMPTY_LIST, EMPTY_LIST_NULLS, EMPTY_SET, EMPTY_MAP }; } else { EMPTY = archivedObjects[0]; EMPTY_LIST = (ListN)archivedObjects[1]; - EMPTY_SET = (SetN)archivedObjects[2]; - EMPTY_MAP = (MapN)archivedObjects[3]; + EMPTY_LIST_NULLS = (ListN)archivedObjects[2]; + EMPTY_SET = (SetN)archivedObjects[3]; + EMPTY_MAP = (MapN)archivedObjects[4]; } } @@ -120,7 +121,10 @@ static class Access { static { SharedSecrets.setJavaUtilCollectionAccess(new JavaUtilCollectionAccess() { public List listFromTrustedArray(Object[] array) { - return ImmutableCollections.ListN.fromTrustedArray(array); + return ImmutableCollections.listFromTrustedArray(array); + } + public List listFromTrustedArrayNullsAllowed(Object[] array) { + return ImmutableCollections.listFromTrustedArrayNullsAllowed(array); } }); } @@ -148,18 +152,101 @@ static abstract class AbstractImmutableCollection extends AbstractCollection< @Override public boolean retainAll(Collection c) { throw uoe(); } } - // ---------- List Implementations ---------- + // ---------- List Static Factory Methods ---------- - // make a copy, short-circuiting based on implementation class + /** + * Copies a collection into a new List, unless the arg is already a safe, + * null-prohibiting unmodifiable list, in which case the arg itself is returned. + * Null argument or null elements in the argument will result in NPE. + * + * @param the List's element type + * @param input the input array + * @return the new list + */ @SuppressWarnings("unchecked") static List listCopy(Collection coll) { - if (coll instanceof AbstractImmutableList && coll.getClass() != SubList.class) { + if (coll instanceof List12 || (coll instanceof ListN && ! ((ListN)coll).allowNulls)) { return (List)coll; } else { - return (List)List.of(coll.toArray()); + return (List)List.of(coll.toArray()); // implicit nullcheck of coll + } + } + + /** + * Creates a new List from an untrusted array, creating a new array for internal + * storage, and checking for and rejecting null elements. + * + * @param the List's element type + * @param input the input array + * @return the new list + */ + @SafeVarargs + static List listFromArray(E... input) { + // copy and check manually to avoid TOCTOU + @SuppressWarnings("unchecked") + E[] tmp = (E[])new Object[input.length]; // implicit nullcheck of input + for (int i = 0; i < input.length; i++) { + tmp[i] = Objects.requireNonNull(input[i]); + } + return new ListN<>(tmp, false); + } + + /** + * Creates a new List from a trusted array, checking for and rejecting null + * elements. + * + *

    A trusted array has no references retained by the caller. It can therefore be + * safely reused as the List's internal storage, avoiding a defensive copy. The array's + * class must be Object[].class. This method is declared with a parameter type of + * Object... instead of E... so that a varargs call doesn't accidentally create an array + * of some class other than Object[].class. + * + * @param the List's element type + * @param input the input array + * @return the new list + */ + @SuppressWarnings("unchecked") + static List listFromTrustedArray(Object... input) { + assert input.getClass() == Object[].class; + for (Object o : input) { // implicit null check of 'input' array + Objects.requireNonNull(o); + } + + return switch (input.length) { + case 0 -> (List) ImmutableCollections.EMPTY_LIST; + case 1 -> (List) new List12<>(input[0]); + case 2 -> (List) new List12<>(input[0], input[1]); + default -> (List) new ListN<>(input, false); + }; + } + + /** + * Creates a new List from a trusted array, allowing null elements. + * + *

    A trusted array has no references retained by the caller. It can therefore be + * safely reused as the List's internal storage, avoiding a defensive copy. The array's + * class must be Object[].class. This method is declared with a parameter type of + * Object... instead of E... so that a varargs call doesn't accidentally create an array + * of some class other than Object[].class. + * + *

    Avoids creating a List12 instance, as it cannot accommodate null elements. + * + * @param the List's element type + * @param input the input array + * @return the new list + */ + @SuppressWarnings("unchecked") + static List listFromTrustedArrayNullsAllowed(Object... input) { + assert input.getClass() == Object[].class; + if (input.length == 0) { + return (List) EMPTY_LIST_NULLS; + } else { + return new ListN<>((E[])input, true); } } + // ---------- List Implementations ---------- + static abstract class AbstractImmutableList extends AbstractImmutableCollection implements List, RandomAccess { @@ -219,40 +306,18 @@ public boolean equals(Object o) { Iterator oit = ((List) o).iterator(); for (int i = 0, s = size(); i < s; i++) { - if (!oit.hasNext() || !get(i).equals(oit.next())) { + if (!oit.hasNext() || !Objects.equals(get(i), oit.next())) { return false; } } return !oit.hasNext(); } - @Override - public int indexOf(Object o) { - Objects.requireNonNull(o); - for (int i = 0, s = size(); i < s; i++) { - if (o.equals(get(i))) { - return i; - } - } - return -1; - } - - @Override - public int lastIndexOf(Object o) { - Objects.requireNonNull(o); - for (int i = size() - 1; i >= 0; i--) { - if (o.equals(get(i))) { - return i; - } - } - return -1; - } - @Override public int hashCode() { int hash = 1; for (int i = 0, s = size(); i < s; i++) { - hash = 31 * hash + get(i).hashCode(); + hash = 31 * hash + Objects.hashCode(get(i)); } return hash; } @@ -361,7 +426,7 @@ static final class SubList extends AbstractImmutableList implements RandomAccess { @Stable - private final List root; + private final AbstractImmutableList root; @Stable private final int offset; @@ -369,7 +434,8 @@ static final class SubList extends AbstractImmutableList @Stable private final int size; - private SubList(List root, int offset, int size) { + private SubList(AbstractImmutableList root, int offset, int size) { + assert root instanceof List12 || root instanceof ListN; this.root = root; this.offset = offset; this.size = size; @@ -386,7 +452,7 @@ static SubList fromSubList(SubList parent, int fromIndex, int toIndex) * Constructs a sublist of an arbitrary AbstractImmutableList, which is * not a SubList itself. */ - static SubList fromList(List list, int fromIndex, int toIndex) { + static SubList fromList(AbstractImmutableList list, int fromIndex, int toIndex) { return new SubList<>(list, fromIndex, toIndex - fromIndex); } @@ -419,6 +485,36 @@ private void rangeCheck(int index) { } } + private boolean allowNulls() { + return root instanceof ListN && ((ListN)root).allowNulls; + } + + @Override + public int indexOf(Object o) { + if (!allowNulls() && o == null) { + throw new NullPointerException(); + } + for (int i = 0, s = size(); i < s; i++) { + if (Objects.equals(o, get(i))) { + return i; + } + } + return -1; + } + + @Override + public int lastIndexOf(Object o) { + if (!allowNulls() && o == null) { + throw new NullPointerException(); + } + for (int i = size() - 1; i >= 0; i--) { + if (Objects.equals(o, get(i))) { + return i; + } + } + return -1; + } + @Override public Object[] toArray() { Object[] array = new Object[size]; @@ -456,7 +552,7 @@ static final class List12 extends AbstractImmutableList List12(E e0) { this.e0 = Objects.requireNonNull(e0); // Use EMPTY as a sentinel for an unused element: not using null - // enable constant folding optimizations over single-element lists + // enables constant folding optimizations over single-element lists this.e1 = EMPTY; } @@ -486,6 +582,30 @@ public E get(int index) { throw outOfBounds(index); } + @Override + public int indexOf(Object o) { + Objects.requireNonNull(o); + if (o.equals(e0)) { + return 0; + } else if (e1 != EMPTY && o.equals(e1)) { + return 1; + } else { + return -1; + } + } + + @Override + public int lastIndexOf(Object o) { + Objects.requireNonNull(o); + if (e1 != EMPTY && o.equals(e1)) { + return 1; + } else if (o.equals(e0)) { + return 0; + } else { + return -1; + } + } + @java.io.Serial private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { throw new InvalidObjectException("not serial proxy"); @@ -532,31 +652,13 @@ static final class ListN extends AbstractImmutableList @Stable private final E[] elements; - private ListN(E[] array) { - elements = array; - } + @Stable + private final boolean allowNulls; - // creates a new internal array, and checks and rejects null elements - @SafeVarargs - static List fromArray(E... input) { - // copy and check manually to avoid TOCTOU - @SuppressWarnings("unchecked") - E[] tmp = (E[])new Object[input.length]; // implicit nullcheck of input - for (int i = 0; i < input.length; i++) { - tmp[i] = Objects.requireNonNull(input[i]); - } - return new ListN<>(tmp); - } - - // Avoids creating a new array, but checks and rejects null elements. - // Declared with Object... arg so that varargs calls don't accidentally - // create an array of a subtype. - @SuppressWarnings("unchecked") - static List fromTrustedArray(Object... input) { - for (Object o : input) { - Objects.requireNonNull(o); - } - return new ListN<>((E[])input); + // caller must ensure that elements has no nulls if allowNulls is false + private ListN(E[] elements, boolean allowNulls) { + this.elements = elements; + this.allowNulls = allowNulls; } @Override @@ -581,7 +683,7 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE @java.io.Serial private Object writeReplace() { - return new CollSer(CollSer.IMM_LIST, elements); + return new CollSer(allowNulls ? CollSer.IMM_LIST_NULLS : CollSer.IMM_LIST, elements); } @Override @@ -603,6 +705,34 @@ public T[] toArray(T[] a) { } return a; } + + @Override + public int indexOf(Object o) { + if (!allowNulls && o == null) { + throw new NullPointerException(); + } + Object[] es = elements; + for (int i = 0; i < es.length; i++) { + if (Objects.equals(o, es[i])) { + return i; + } + } + return -1; + } + + @Override + public int lastIndexOf(Object o) { + if (!allowNulls && o == null) { + throw new NullPointerException(); + } + Object[] es = elements; + for (int i = es.length - 1; i >= 0; i--) { + if (Objects.equals(o, es[i])) { + return i; + } + } + return -1; + } } // ---------- Set Implementations ---------- @@ -1225,15 +1355,19 @@ final class CollSer implements Serializable { @java.io.Serial private static final long serialVersionUID = 6309168927139932177L; - static final int IMM_LIST = 1; - static final int IMM_SET = 2; - static final int IMM_MAP = 3; + static final int IMM_LIST = 1; + static final int IMM_SET = 2; + static final int IMM_MAP = 3; + static final int IMM_LIST_NULLS = 4; /** * Indicates the type of collection that is serialized. * The low order 8 bits have the value 1 for an immutable - * {@code List}, 2 for an immutable {@code Set}, and 3 for - * an immutable {@code Map}. Any other value causes an + * {@code List}, 2 for an immutable {@code Set}, 3 for + * an immutable {@code Map}, and 4 for an immutable + * {@code List} that allows null elements. + * + * Any other value causes an * {@link InvalidObjectException} to be thrown. The high * order 24 bits are zero when an instance is serialized, * and they are ignored when an instance is deserialized. @@ -1340,7 +1474,7 @@ private void writeObject(ObjectOutputStream oos) throws IOException { * @throws ObjectStreamException if another serialization error has occurred * @since 9 */ - @java.io.Serial + @java.io.Serial private Object readResolve() throws ObjectStreamException { try { if (array == null) { @@ -1352,6 +1486,9 @@ private Object readResolve() throws ObjectStreamException { switch (tag & 0xff) { case IMM_LIST: return List.of(array); + case IMM_LIST_NULLS: + return ImmutableCollections.listFromTrustedArrayNullsAllowed( + Arrays.copyOf(array, array.length, Object[].class)); case IMM_SET: return Set.of(array); case IMM_MAP: diff --git a/src/java.base/share/classes/java/util/List.java b/src/java.base/share/classes/java/util/List.java index 2496ae6dc6d..314fb6af6c1 100644 --- a/src/java.base/share/classes/java/util/List.java +++ b/src/java.base/share/classes/java/util/List.java @@ -842,7 +842,7 @@ static List of(E e1, E e2) { * @since 9 */ static List of(E e1, E e2, E e3) { - return ImmutableCollections.ListN.fromTrustedArray(e1, e2, e3); + return ImmutableCollections.listFromTrustedArray(e1, e2, e3); } /** @@ -861,7 +861,7 @@ static List of(E e1, E e2, E e3) { * @since 9 */ static List of(E e1, E e2, E e3, E e4) { - return ImmutableCollections.ListN.fromTrustedArray(e1, e2, e3, e4); + return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4); } /** @@ -881,7 +881,7 @@ static List of(E e1, E e2, E e3, E e4) { * @since 9 */ static List of(E e1, E e2, E e3, E e4, E e5) { - return ImmutableCollections.ListN.fromTrustedArray(e1, e2, e3, e4, e5); + return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5); } /** @@ -902,8 +902,8 @@ static List of(E e1, E e2, E e3, E e4, E e5) { * @since 9 */ static List of(E e1, E e2, E e3, E e4, E e5, E e6) { - return ImmutableCollections.ListN.fromTrustedArray(e1, e2, e3, e4, e5, - e6); + return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5, + e6); } /** @@ -925,8 +925,8 @@ static List of(E e1, E e2, E e3, E e4, E e5, E e6) { * @since 9 */ static List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) { - return ImmutableCollections.ListN.fromTrustedArray(e1, e2, e3, e4, e5, - e6, e7); + return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5, + e6, e7); } /** @@ -949,8 +949,8 @@ static List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) { * @since 9 */ static List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) { - return ImmutableCollections.ListN.fromTrustedArray(e1, e2, e3, e4, e5, - e6, e7, e8); + return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5, + e6, e7, e8); } /** @@ -974,8 +974,8 @@ static List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) { * @since 9 */ static List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) { - return ImmutableCollections.ListN.fromTrustedArray(e1, e2, e3, e4, e5, - e6, e7, e8, e9); + return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5, + e6, e7, e8, e9); } /** @@ -1000,8 +1000,8 @@ static List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) { * @since 9 */ static List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) { - return ImmutableCollections.ListN.fromTrustedArray(e1, e2, e3, e4, e5, - e6, e7, e8, e9, e10); + return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5, + e6, e7, e8, e9, e10); } /** @@ -1042,7 +1042,7 @@ static List of(E... elements) { case 2: return new ImmutableCollections.List12<>(elements[0], elements[1]); default: - return ImmutableCollections.ListN.fromArray(elements); + return ImmutableCollections.listFromArray(elements); } } diff --git a/src/java.base/share/classes/java/util/stream/ReferencePipeline.java b/src/java.base/share/classes/java/util/stream/ReferencePipeline.java index d13b649ecd5..b001cb08818 100644 --- a/src/java.base/share/classes/java/util/stream/ReferencePipeline.java +++ b/src/java.base/share/classes/java/util/stream/ReferencePipeline.java @@ -26,6 +26,7 @@ import java.util.Comparator; import java.util.Iterator; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Spliterator; @@ -44,6 +45,7 @@ import java.util.function.ToDoubleFunction; import java.util.function.ToIntFunction; import java.util.function.ToLongFunction; +import jdk.internal.access.SharedSecrets; /** * Abstract base class for an intermediate pipeline stage or pipeline source @@ -620,6 +622,11 @@ public final Object[] toArray() { return toArray(Object[]::new); } + @Override + public List toList() { + return SharedSecrets.getJavaUtilCollectionAccess().listFromTrustedArrayNullsAllowed(this.toArray()); + } + @Override public final boolean anyMatch(Predicate predicate) { return evaluate(MatchOps.makeRef(predicate, MatchOps.MatchKind.ANY)); diff --git a/src/java.base/share/classes/java/util/stream/Stream.java b/src/java.base/share/classes/java/util/stream/Stream.java index d00740bb830..feed9303cd6 100644 --- a/src/java.base/share/classes/java/util/stream/Stream.java +++ b/src/java.base/share/classes/java/util/stream/Stream.java @@ -1162,6 +1162,40 @@ R collect(Supplier supplier, */ R collect(Collector collector); + /** + * Accumulates the elements of this stream into a {@code List}. The elements in + * the list will be in this stream's encounter order, if one exists. The returned List + * is unmodifiable; calls to any mutator method will always cause + * {@code UnsupportedOperationException} to be thrown. There are no + * guarantees on the implementation type or serializability of the returned List. + * + *

    The returned instance may be value-based. + * Callers should make no assumptions about the identity of the returned instances. + * Identity-sensitive operations on these instances (reference equality ({@code ==}), + * identity hash code, and synchronization) are unreliable and should be avoided. + * + *

    This is a terminal operation. + * + * @apiNote If more control over the returned object is required, use + * {@link Collectors#toCollection(Supplier)}. + * + * @implSpec The implementation in this interface returns a List produced as if by the following: + *

    {@code
    +     * Collections.unmodifiableList(new ArrayList<>(Arrays.asList(this.toArray())))
    +     * }
    + * + * @implNote Most instances of Stream will override this method and provide an implementation + * that is highly optimized compared to the implementation in this interface. + * + * @return a List containing the stream elements + * + * @since 16 + */ + @SuppressWarnings("unchecked") + default List toList() { + return (List) Collections.unmodifiableList(new ArrayList<>(Arrays.asList(this.toArray()))); + } + /** * Returns the minimum element of this stream according to the provided * {@code Comparator}. This is a special case of a diff --git a/src/java.base/share/classes/jdk/internal/access/JavaUtilCollectionAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaUtilCollectionAccess.java index 137b2828299..f88d57521ac 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaUtilCollectionAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaUtilCollectionAccess.java @@ -29,4 +29,5 @@ public interface JavaUtilCollectionAccess { List listFromTrustedArray(Object[] array); + List listFromTrustedArrayNullsAllowed(Object[] array); } diff --git a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java index de3e25b69b1..98c8b8971a5 100644 --- a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java +++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java @@ -1345,6 +1345,7 @@ public native Class defineClass0(String name, byte[] b, int off, int len, * @param data bytes of a class file * @param cpPatches where non-null entries exist, they replace corresponding CP entries in data */ + @Deprecated(since = "15", forRemoval = true) public Class defineAnonymousClass(Class hostClass, byte[] data, Object[] cpPatches) { if (hostClass == null || data == null) { throw new NullPointerException(); diff --git a/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java b/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java index ed33151ad44..eab3afae080 100644 --- a/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java +++ b/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java @@ -39,6 +39,7 @@ public class VerifyAccess { private VerifyAccess() { } // cannot instantiate private static final int UNCONDITIONAL_ALLOWED = java.lang.invoke.MethodHandles.Lookup.UNCONDITIONAL; + private static final int ORIGINAL_ALLOWED = java.lang.invoke.MethodHandles.Lookup.ORIGINAL; private static final int MODULE_ALLOWED = java.lang.invoke.MethodHandles.Lookup.MODULE; private static final int PACKAGE_ONLY = 0; private static final int PACKAGE_ALLOWED = java.lang.invoke.MethodHandles.Lookup.PACKAGE; @@ -99,7 +100,7 @@ public static boolean isMemberAccessible(Class refc, // symbolic ref class Class prevLookupClass, int allowedModes) { if (allowedModes == 0) return false; - assert((allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED|MODULE_ALLOWED|UNCONDITIONAL_ALLOWED)) == 0); + assert((allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED|MODULE_ALLOWED|UNCONDITIONAL_ALLOWED|ORIGINAL_ALLOWED)) == 0); // The symbolic reference class (refc) must always be fully verified. if (!isClassAccessible(refc, lookupClass, prevLookupClass, allowedModes)) { return false; @@ -189,7 +190,7 @@ public static boolean isClassAccessible(Class refc, Class prevLookupClass, int allowedModes) { if (allowedModes == 0) return false; - assert((allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED|MODULE_ALLOWED|UNCONDITIONAL_ALLOWED)) == 0); + assert((allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED|MODULE_ALLOWED|UNCONDITIONAL_ALLOWED|ORIGINAL_ALLOWED)) == 0); if ((allowedModes & PACKAGE_ALLOWED) != 0 && isSamePackage(lookupClass, refc)) diff --git a/src/java.base/share/classes/sun/security/ssl/Alert.java b/src/java.base/share/classes/sun/security/ssl/Alert.java index b6f2642cf7d..bc034dc8c3b 100644 --- a/src/java.base/share/classes/sun/security/ssl/Alert.java +++ b/src/java.base/share/classes/sun/security/ssl/Alert.java @@ -123,7 +123,7 @@ SSLException createSSLException(String reason, Throwable cause) { } SSLException ssle; - if ((cause != null) && (cause instanceof IOException)) { + if (cause instanceof IOException) { ssle = new SSLException(reason); } else if ((this == UNEXPECTED_MESSAGE)) { ssle = new SSLProtocolException(reason); diff --git a/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java b/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java index 79b8eebd89e..398a84790db 100644 --- a/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java @@ -370,7 +370,7 @@ static List getRequestedServerNames(SSLEngine engine) { private static List getRequestedServerNames( SSLSession session) { - if (session != null && (session instanceof ExtendedSSLSession)) { + if (session instanceof ExtendedSSLSession) { return ((ExtendedSSLSession)session).getRequestedServerNames(); } diff --git a/src/java.base/share/classes/sun/security/util/CurveDB.java b/src/java.base/share/classes/sun/security/util/CurveDB.java index e16e5238fd1..74f5cb073f5 100644 --- a/src/java.base/share/classes/sun/security/util/CurveDB.java +++ b/src/java.base/share/classes/sun/security/util/CurveDB.java @@ -365,7 +365,7 @@ private static void add(KnownOIDs o, int type, String sfield, "0400000000000000016954A233049BA98F", 2); - add(KnownOIDs.sect163k1, BD, + add(KnownOIDs.sect163k1, B, "0800000000000000000000000000000000000000C9", "000000000000000000000000000000000000000001", "000000000000000000000000000000000000000001", diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/Functions.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/Functions.java index 7e5593f8703..7d8f32a6cce 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/Functions.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/Functions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 2002 Graz University of Technology. All rights reserved. @@ -54,7 +54,7 @@ import static sun.security.pkcs11.wrapper.PKCS11Constants.*; /** - * This class contains onyl static methods. It is the place for all functions + * This class contains only static methods. It is the place for all functions * that are used by several classes in this package. * * @author Karl Scheibelhofer @@ -350,6 +350,12 @@ public static String sessionStateToString(long state) { private static final Flags mechanismInfoFlags = new Flags(new long[] { CKF_HW, + CKF_MESSAGE_ENCRYPT, + CKF_MESSAGE_DECRYPT, + CKF_MESSAGE_SIGN, + CKF_MESSAGE_VERIFY, + CKF_MULTI_MESSAGE, + CKF_FIND_OBJECTS, CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, @@ -365,12 +371,19 @@ public static String sessionStateToString(long state) { CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, - CKF_EC_NAMEDCURVE, + CKF_EC_OID, CKF_EC_UNCOMPRESS, CKF_EC_COMPRESS, + CKF_EC_CURVENAME, CKF_EXTENSION, }, new String[] { "CKF_HW", + "CKF_MESSAGE_ENCRYPT", + "CKF_MESSAGE_DECRYPT", + "CKF_MESSAGE_SIGN", + "CKF_MESSAGE_VERIFY", + "CKF_MULTI_MESSAGE", + "CKF_FIND_OBJECTS", "CKF_ENCRYPT", "CKF_DECRYPT", "CKF_DIGEST", @@ -386,9 +399,10 @@ public static String sessionStateToString(long state) { "CKF_EC_F_P", "CKF_EC_F_2M", "CKF_EC_ECPARAMETERS", - "CKF_EC_NAMEDCURVE", + "CKF_EC_OID", "CKF_EC_UNCOMPRESS", "CKF_EC_COMPRESS", + "CKF_EC_CURVENAME", "CKF_EXTENSION", }); @@ -624,6 +638,7 @@ private static void addMGF(long id, String name) { addMapping(mgfNames, mgfIds, id, name); } + // The ordering here follows the PKCS11Constants class static { addMech(CKM_RSA_PKCS_KEY_PAIR_GEN, "CKM_RSA_PKCS_KEY_PAIR_GEN"); addMech(CKM_RSA_PKCS, "CKM_RSA_PKCS"); @@ -647,6 +662,10 @@ private static void addMGF(long id, String name) { addMech(CKM_DSA_SHA256, "CKM_DSA_SHA256"); addMech(CKM_DSA_SHA384, "CKM_DSA_SHA384"); addMech(CKM_DSA_SHA512, "CKM_DSA_SHA512"); + addMech(CKM_DSA_SHA3_224, "CKM_DSA_SHA3_224"); + addMech(CKM_DSA_SHA3_256, "CKM_DSA_SHA3_256"); + addMech(CKM_DSA_SHA3_384, "CKM_DSA_SHA3_384"); + addMech(CKM_DSA_SHA3_512, "CKM_DSA_SHA3_512"); addMech(CKM_DH_PKCS_KEY_PAIR_GEN, "CKM_DH_PKCS_KEY_PAIR_GEN"); addMech(CKM_DH_PKCS_DERIVE, "CKM_DH_PKCS_DERIVE"); @@ -664,6 +683,28 @@ private static void addMGF(long id, String name) { addMech(CKM_SHA224_RSA_PKCS, "CKM_SHA224_RSA_PKCS"); addMech(CKM_SHA224_RSA_PKCS_PSS, "CKM_SHA224_RSA_PKCS_PSS"); + addMech(CKM_SHA512_224, "CKM_SHA512_224"); + addMech(CKM_SHA512_224_HMAC, "CKM_SHA512_224_HMAC"); + addMech(CKM_SHA512_224_HMAC_GENERAL, "CKM_SHA512_224_HMAC_GENERAL"); + addMech(CKM_SHA512_224_KEY_DERIVATION, "CKM_SHA512_224_KEY_DERIVATION"); + addMech(CKM_SHA512_256, "CKM_SHA512_256"); + addMech(CKM_SHA512_256_HMAC, "CKM_SHA512_256_HMAC"); + addMech(CKM_SHA512_256_HMAC_GENERAL, "CKM_SHA512_256_HMAC_GENERAL"); + addMech(CKM_SHA512_256_KEY_DERIVATION, "CKM_SHA512_256_KEY_DERIVATION"); + addMech(CKM_SHA512_T, "CKM_SHA512_T"); + addMech(CKM_SHA512_T_HMAC, "CKM_SHA512_T_HMAC"); + addMech(CKM_SHA512_T_HMAC_GENERAL, "CKM_SHA512_T_HMAC_GENERAL"); + addMech(CKM_SHA512_T_KEY_DERIVATION, "CKM_SHA512_T_KEY_DERIVATION"); + + addMech(CKM_SHA3_256_RSA_PKCS, "CKM_SHA3_256_RSA_PKCS"); + addMech(CKM_SHA3_384_RSA_PKCS, "CKM_SHA3_384_RSA_PKCS"); + addMech(CKM_SHA3_512_RSA_PKCS, "CKM_SHA3_512_RSA_PKCS"); + addMech(CKM_SHA3_256_RSA_PKCS_PSS, "CKM_SHA3_256_RSA_PKCS_PSS"); + addMech(CKM_SHA3_384_RSA_PKCS_PSS, "CKM_SHA3_384_RSA_PKCS_PSS"); + addMech(CKM_SHA3_512_RSA_PKCS_PSS, "CKM_SHA3_512_RSA_PKCS_PSS"); + addMech(CKM_SHA3_224_RSA_PKCS, "CKM_SHA3_224_RSA_PKCS"); + addMech(CKM_SHA3_224_RSA_PKCS_PSS, "CKM_SHA3_224_RSA_PKCS_PSS"); + addMech(CKM_RC2_KEY_GEN, "CKM_RC2_KEY_GEN"); addMech(CKM_RC2_ECB, "CKM_RC2_ECB"); addMech(CKM_RC2_CBC, "CKM_RC2_CBC"); @@ -715,30 +756,18 @@ private static void addMGF(long id, String name) { addMech(CKM_RIPEMD160, "CKM_RIPEMD160"); addMech(CKM_RIPEMD160_HMAC, "CKM_RIPEMD160_HMAC"); addMech(CKM_RIPEMD160_HMAC_GENERAL, "CKM_RIPEMD160_HMAC_GENERAL"); - addMech(CKM_SHA224, "CKM_SHA224"); - addMech(CKM_SHA224_HMAC, "CKM_SHA224_HMAC"); - addMech(CKM_SHA224_HMAC_GENERAL, "CKM_SHA224_HMAC_GENERAL"); addMech(CKM_SHA256, "CKM_SHA256"); addMech(CKM_SHA256_HMAC, "CKM_SHA256_HMAC"); addMech(CKM_SHA256_HMAC_GENERAL, "CKM_SHA256_HMAC_GENERAL"); + addMech(CKM_SHA224, "CKM_SHA224"); + addMech(CKM_SHA224_HMAC, "CKM_SHA224_HMAC"); + addMech(CKM_SHA224_HMAC_GENERAL, "CKM_SHA224_HMAC_GENERAL"); addMech(CKM_SHA384, "CKM_SHA384"); addMech(CKM_SHA384_HMAC, "CKM_SHA384_HMAC"); addMech(CKM_SHA384_HMAC_GENERAL, "CKM_SHA384_HMAC_GENERAL"); addMech(CKM_SHA512, "CKM_SHA512"); addMech(CKM_SHA512_HMAC, "CKM_SHA512_HMAC"); addMech(CKM_SHA512_HMAC_GENERAL, "CKM_SHA512_HMAC_GENERAL"); - addMech(CKM_SHA512_224, "CKM_SHA512_224"); - addMech(CKM_SHA512_224_HMAC, "CKM_SHA512_224_HMAC"); - addMech(CKM_SHA512_224_HMAC_GENERAL, "CKM_SHA512_224_HMAC_GENERAL"); - addMech(CKM_SHA512_224_KEY_DERIVATION, "CKM_SHA512_224_KEY_DERIVATION"); - addMech(CKM_SHA512_256, "CKM_SHA512_256"); - addMech(CKM_SHA512_256_HMAC, "CKM_SHA512_256_HMAC"); - addMech(CKM_SHA512_256_HMAC_GENERAL, "CKM_SHA512_256_HMAC_GENERAL"); - addMech(CKM_SHA512_256_KEY_DERIVATION, "CKM_SHA512_256_KEY_DERIVATION"); - addMech(CKM_SHA512_T, "CKM_SHA512_T"); - addMech(CKM_SHA512_T_HMAC, "CKM_SHA512_T_HMAC"); - addMech(CKM_SHA512_T_HMAC_GENERAL, "CKM_SHA512_T_HMAC_GENERAL"); - addMech(CKM_SHA512_T_KEY_DERIVATION, "CKM_SHA512_T_KEY_DERIVATION"); addMech(CKM_SECURID_KEY_GEN, "CKM_SECURID_KEY_GEN"); addMech(CKM_SECURID, "CKM_SECURID"); @@ -747,6 +776,23 @@ private static void addMGF(long id, String name) { addMech(CKM_ACTI, "CKM_ACTI"); addMech(CKM_ACTI_KEY_GEN, "CKM_ACTI_KEY_GEN"); + addMech(CKM_SHA3_256, "CKM_SHA3_256"); + addMech(CKM_SHA3_256_HMAC, "CKM_SHA3_256_HMAC"); + addMech(CKM_SHA3_256_HMAC_GENERAL, "CKM_SHA3_256_HMAC_GENERAL"); + addMech(CKM_SHA3_256_KEY_GEN, "CKM_SHA3_256_KEY_GEN"); + addMech(CKM_SHA3_224, "CKM_SHA3_224"); + addMech(CKM_SHA3_224_HMAC, "CKM_SHA3_224_HMAC"); + addMech(CKM_SHA3_224_HMAC_GENERAL, "CKM_SHA3_224_HMAC_GENERAL"); + addMech(CKM_SHA3_224_KEY_GEN, "CKM_SHA3_224_KEY_GEN"); + addMech(CKM_SHA3_384, "CKM_SHA3_384"); + addMech(CKM_SHA3_384_HMAC, "CKM_SHA3_384_HMAC"); + addMech(CKM_SHA3_384_HMAC_GENERAL, "CKM_SHA3_384_HMAC_GENERAL"); + addMech(CKM_SHA3_384_KEY_GEN, "CKM_SHA3_384_KEY_GEN"); + addMech(CKM_SHA3_512, "CKM_SHA3_512"); + addMech(CKM_SHA3_512_HMAC, "CKM_SHA3_512_HMAC"); + addMech(CKM_SHA3_512_HMAC_GENERAL, "CKM_SHA3_512_HMAC_GENERAL"); + addMech(CKM_SHA3_512_KEY_GEN, "CKM_SHA3_512_KEY_GEN"); + addMech(CKM_CAST_KEY_GEN, "CKM_CAST_KEY_GEN"); addMech(CKM_CAST_ECB, "CKM_CAST_ECB"); addMech(CKM_CAST_CBC, "CKM_CAST_CBC"); @@ -798,10 +844,17 @@ private static void addMGF(long id, String name) { addMech(CKM_MD5_KEY_DERIVATION, "CKM_MD5_KEY_DERIVATION"); addMech(CKM_MD2_KEY_DERIVATION, "CKM_MD2_KEY_DERIVATION"); addMech(CKM_SHA1_KEY_DERIVATION, "CKM_SHA1_KEY_DERIVATION"); - addMech(CKM_SHA224_KEY_DERIVATION, "CKM_SHA224_KEY_DERIVATION"); addMech(CKM_SHA256_KEY_DERIVATION, "CKM_SHA256_KEY_DERIVATION"); addMech(CKM_SHA384_KEY_DERIVATION, "CKM_SHA384_KEY_DERIVATION"); addMech(CKM_SHA512_KEY_DERIVATION, "CKM_SHA512_KEY_DERIVATION"); + addMech(CKM_SHA224_KEY_DERIVATION, "CKM_SHA224_KEY_DERIVATION"); + addMech(CKM_SHA3_256_KEY_DERIVATION, "CKM_SHA3_256_KEY_DERIVATION"); + addMech(CKM_SHA3_224_KEY_DERIVATION, "CKM_SHA3_224_KEY_DERIVATION"); + addMech(CKM_SHA3_384_KEY_DERIVATION, "CKM_SHA3_384_KEY_DERIVATION"); + addMech(CKM_SHA3_512_KEY_DERIVATION, "CKM_SHA3_512_KEY_DERIVATION"); + addMech(CKM_SHAKE_128_KEY_DERIVATION, "CKM_SHAKE_128_KEY_DERIVATION"); + addMech(CKM_SHAKE_256_KEY_DERIVATION, "CKM_SHAKE_256_KEY_DERIVATION"); + addMech(CKM_PBE_MD2_DES_CBC, "CKM_PBE_MD2_DES_CBC"); addMech(CKM_PBE_MD5_DES_CBC, "CKM_PBE_MD5_DES_CBC"); addMech(CKM_PBE_MD5_CAST_CBC, "CKM_PBE_MD5_CAST_CBC"); @@ -894,18 +947,29 @@ private static void addMGF(long id, String name) { addMech(CKM_BATON_SHUFFLE, "CKM_BATON_SHUFFLE"); addMech(CKM_BATON_WRAP, "CKM_BATON_WRAP"); addMech(CKM_EC_KEY_PAIR_GEN, "CKM_EC_KEY_PAIR_GEN"); + addMech(CKM_EC_KEY_PAIR_GEN_W_EXTRA_BITS, + "CKM_EC_KEY_PAIR_GEN_W_EXTRA_BITS"); + addMech(CKM_ECDSA, "CKM_ECDSA"); addMech(CKM_ECDSA_SHA1, "CKM_ECDSA_SHA1"); addMech(CKM_ECDSA_SHA224, "CKM_ECDSA_SHA224"); addMech(CKM_ECDSA_SHA256, "CKM_ECDSA_SHA256"); addMech(CKM_ECDSA_SHA384, "CKM_ECDSA_SHA384"); addMech(CKM_ECDSA_SHA512, "CKM_ECDSA_SHA512"); + addMech(CKM_ECDSA_SHA3_224, "CKM_ECDSA_SHA3_224"); + addMech(CKM_ECDSA_SHA3_256, "CKM_ECDSA_SHA3_256"); + addMech(CKM_ECDSA_SHA3_384, "CKM_ECDSA_SHA3_384"); + addMech(CKM_ECDSA_SHA3_512, "CKM_ECDSA_SHA3_512"); addMech(CKM_ECDH1_DERIVE, "CKM_ECDH1_DERIVE"); addMech(CKM_ECDH1_COFACTOR_DERIVE, "CKM_ECDH1_COFACTOR_DERIVE"); addMech(CKM_ECMQV_DERIVE, "CKM_ECMQV_DERIVE"); addMech(CKM_ECDH_AES_KEY_WRAP, "CKM_ECDH_AES_KEY_WRAP"); addMech(CKM_RSA_AES_KEY_WRAP, "CKM_RSA_AES_KEY_WRAP"); + addMech(CKM_EC_EDWARDS_KEY_PAIR_GEN, "CKM_EC_EDWARDS_KEY_PAIR_GEN"); + addMech(CKM_EC_MONTGOMERY_KEY_PAIR_GEN, + "CKM_EC_MONTGOMERY_KEY_PAIR_GEN"); + addMech(CKM_EDDSA, "CKM_EDDSA"); addMech(CKM_JUNIPER_KEY_GEN, "CKM_JUNIPER_KEY_GEN"); addMech(CKM_JUNIPER_ECB128, "CKM_JUNIPER_ECB128"); @@ -914,6 +978,9 @@ private static void addMGF(long id, String name) { addMech(CKM_JUNIPER_SHUFFLE, "CKM_JUNIPER_SHUFFLE"); addMech(CKM_JUNIPER_WRAP, "CKM_JUNIPER_WRAP"); addMech(CKM_FASTHASH, "CKM_FASTHASH"); + addMech(CKM_AES_XTS, "CKM_AES_XTS"); + addMech(CKM_AES_XTS_KEY_GEN, "CKM_AES_XTS_KEY_GEN"); + addMech(CKM_AES_KEY_GEN, "CKM_AES_KEY_GEN"); addMech(CKM_AES_ECB, "CKM_AES_ECB"); addMech(CKM_AES_CBC, "CKM_AES_CBC"); @@ -956,6 +1023,10 @@ private static void addMGF(long id, String name) { addMech(CKM_GOST28147, "CKM_GOST28147"); addMech(CKM_GOST28147_MAC, "CKM_GOST28147_MAC"); addMech(CKM_GOST28147_KEY_WRAP, "CKM_GOST28147_KEY_WRAP"); + addMech(CKM_CHACHA20_KEY_GEN, "CKM_CHACHA20_KEY_GEN"); + addMech(CKM_CHACHA20, "CKM_CHACHA20"); + addMech(CKM_POLY1305_KEY_GEN, "CKM_POLY1305_KEY_GEN"); + addMech(CKM_POLY1305, "CKM_POLY1305"); addMech(CKM_DSA_PARAMETER_GEN, "CKM_DSA_PARAMETER_GEN"); addMech(CKM_DH_PKCS_PARAMETER_GEN, "CKM_DH_PKCS_PARAMETER_GEN"); @@ -964,6 +1035,8 @@ private static void addMGF(long id, String name) { "CKM_DSA_PROBABLISTIC_PARAMETER_GEN"); addMech(CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN, "CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN"); + addMech(CKM_DSA_FIPS_G_GEN, "CKM_DSA_FIPS_G_GEN"); + addMech(CKM_AES_OFB, "CKM_AES_OFB"); addMech(CKM_AES_CFB64, "CKM_AES_CFB64"); addMech(CKM_AES_CFB8, "CKM_AES_CFB8"); @@ -971,9 +1044,56 @@ private static void addMGF(long id, String name) { addMech(CKM_AES_CFB1, "CKM_AES_CFB1"); addMech(CKM_AES_KEY_WRAP, "CKM_AES_KEY_WRAP"); addMech(CKM_AES_KEY_WRAP_PAD, "CKM_AES_KEY_WRAP_PAD"); - + addMech(CKM_AES_KEY_WRAP_KWP, "CKM_AES_KEY_WRAP_KWP"); addMech(CKM_RSA_PKCS_TPM_1_1, "CKM_RSA_PKCS_TPM_1_1"); addMech(CKM_RSA_PKCS_OAEP_TPM_1_1, "CKM_RSA_PKCS_OAEP_TPM_1_1"); + addMech(CKM_SHA_1_KEY_GEN, "CKM_SHA_1_KEY_GEN"); + addMech(CKM_SHA224_KEY_GEN, "CKM_SHA224_KEY_GEN"); + addMech(CKM_SHA256_KEY_GEN, "CKM_SHA256_KEY_GEN"); + addMech(CKM_SHA384_KEY_GEN, "CKM_SHA384_KEY_GEN"); + addMech(CKM_SHA512_KEY_GEN, "CKM_SHA512_KEY_GEN"); + addMech(CKM_SHA512_224_KEY_GEN, "CKM_SHA512_224_KEY_GEN"); + addMech(CKM_SHA512_256_KEY_GEN, "CKM_SHA512_256_KEY_GEN"); + addMech(CKM_SHA512_T_KEY_GEN, "CKM_SHA512_T_KEY_GEN"); + addMech(CKM_NULL, "CKM_NULL"); + addMech(CKM_BLAKE2B_160, "CKM_BLAKE2B_160"); + addMech(CKM_BLAKE2B_160_HMAC, "CKM_BLAKE2B_160_HMAC"); + addMech(CKM_BLAKE2B_160_HMAC_GENERAL, "CKM_BLAKE2B_160_HMAC_GENERAL"); + addMech(CKM_BLAKE2B_160_KEY_DERIVE, "CKM_BLAKE2B_160_KEY_DERIVE"); + addMech(CKM_BLAKE2B_160_KEY_GEN, "CKM_BLAKE2B_160_KEY_GEN"); + addMech(CKM_BLAKE2B_256, "CKM_BLAKE2B_256"); + addMech(CKM_BLAKE2B_256_HMAC, "CKM_BLAKE2B_256_HMAC"); + addMech(CKM_BLAKE2B_256_HMAC_GENERAL, "CKM_BLAKE2B_256_HMAC_GENERAL"); + addMech(CKM_BLAKE2B_256_KEY_DERIVE, "CKM_BLAKE2B_256_KEY_DERIVE"); + addMech(CKM_BLAKE2B_256_KEY_GEN, "CKM_BLAKE2B_256_KEY_GEN"); + addMech(CKM_BLAKE2B_384, "CKM_BLAKE2B_384"); + addMech(CKM_BLAKE2B_384_HMAC, "CKM_BLAKE2B_384_HMAC"); + addMech(CKM_BLAKE2B_384_HMAC_GENERAL, "CKM_BLAKE2B_384_HMAC_GENERAL"); + addMech(CKM_BLAKE2B_384_KEY_DERIVE, "CKM_BLAKE2B_384_KEY_DERIVE"); + addMech(CKM_BLAKE2B_384_KEY_GEN, "CKM_BLAKE2B_384_KEY_GEN"); + addMech(CKM_BLAKE2B_512, "CKM_BLAKE2B_512"); + addMech(CKM_BLAKE2B_512_HMAC, "CKM_BLAKE2B_512_HMAC"); + addMech(CKM_BLAKE2B_512_HMAC_GENERAL, "CKM_BLAKE2B_512_HMAC_GENERAL"); + addMech(CKM_BLAKE2B_512_KEY_DERIVE, "CKM_BLAKE2B_512_KEY_DERIVE"); + addMech(CKM_BLAKE2B_512_KEY_GEN, "CKM_BLAKE2B_512_KEY_GEN"); + addMech(CKM_SALSA20, "CKM_SALSA20"); + addMech(CKM_CHACHA20_POLY1305, "CKM_CHACHA20_POLY1305"); + addMech(CKM_SALSA20_POLY1305, "CKM_SALSA20_POLY1305"); + addMech(CKM_X3DH_INITIALIZE, "CKM_X3DH_INITIALIZE"); + addMech(CKM_X3DH_RESPOND, "CKM_X3DH_RESPOND"); + addMech(CKM_X2RATCHET_INITIALIZE, "CKM_X2RATCHET_INITIALIZE"); + addMech(CKM_X2RATCHET_RESPOND, "CKM_X2RATCHET_RESPOND"); + addMech(CKM_X2RATCHET_ENCRYPT, "CKM_X2RATCHET_ENCRYPT"); + addMech(CKM_X2RATCHET_DECRYPT, "CKM_X2RATCHET_DECRYPT"); + addMech(CKM_XEDDSA, "CKM_XEDDSA"); + addMech(CKM_HKDF_DERIVE, "CKM_HKDF_DERIVE"); + addMech(CKM_HKDF_DATA, "CKM_HKDF_DATA"); + addMech(CKM_HKDF_KEY_GEN, "CKM_HKDF_KEY_GEN"); + addMech(CKM_SALSA20_KEY_GEN, "CKM_SALSA20_KEY_GEN"); + addMech(CKM_SP800_108_COUNTER_KDF, "CKM_SP800_108_COUNTER_KDF"); + addMech(CKM_SP800_108_FEEDBACK_KDF, "CKM_SP800_108_FEEDBACK_KDF"); + addMech(CKM_SP800_108_DOUBLE_PIPELINE_KDF, + "CKM_SP800_108_DOUBLE_PIPELINE_KDF"); addMech(CKM_VENDOR_DEFINED, "CKM_VENDOR_DEFINED"); @@ -989,6 +1109,10 @@ private static void addMGF(long id, String name) { addHashMech(CKM_SHA512, "SHA-512", "SHA512"); addHashMech(CKM_SHA512_224, "SHA-512/224", "SHA512/224"); addHashMech(CKM_SHA512_256, "SHA-512/256", "SHA512/256"); + addHashMech(CKM_SHA3_224, "SHA3-224"); + addHashMech(CKM_SHA3_256, "SHA3-256"); + addHashMech(CKM_SHA3_384, "SHA3-384"); + addHashMech(CKM_SHA3_512, "SHA3-512"); addKeyType(CKK_RSA, "CKK_RSA"); addKeyType(CKK_DSA, "CKK_DSA"); @@ -1031,6 +1155,27 @@ private static void addMGF(long id, String name) { addKeyType(CKK_GOSTR3410, "CKK_GOSTR3410"); addKeyType(CKK_GOSTR3411, "CKK_GOSTR3411"); addKeyType(CKK_GOST28147, "CKK_GOST28147"); + addKeyType(CKK_CHACHA20, "CKK_CHACHA20"); + addKeyType(CKK_POLY1305, "CKK_POLY1305"); + addKeyType(CKK_AES_XTS, "CKK_AES_XTS"); + + addKeyType(CKK_SHA3_224_HMAC, "CKK_SHA3_224_HMAC"); + addKeyType(CKK_SHA3_256_HMAC, "CKK_SHA3_256_HMAC"); + addKeyType(CKK_SHA3_384_HMAC, "CKK_SHA3_384_HMAC"); + addKeyType(CKK_SHA3_512_HMAC, "CKK_SHA3_512_HMAC"); + addKeyType(CKK_BLAKE2B_160_HMAC, "CKK_BLAKE2B_160_HMAC"); + addKeyType(CKK_BLAKE2B_256_HMAC, "CKK_BLAKE2B_256_HMAC"); + addKeyType(CKK_BLAKE2B_384_HMAC, "CKK_BLAKE2B_384_HMAC"); + addKeyType(CKK_BLAKE2B_512_HMAC, "CKK_BLAKE2B_512_HMAC"); + addKeyType(CKK_SALSA20, "CKK_SALSA20"); + addKeyType(CKK_X2RATCHET, "CKK_X2RATCHET"); + addKeyType(CKK_EC_EDWARDS, "CKK_EC_EDWARDS"); + addKeyType(CKK_EC_MONTGOMERY, "CKK_EC_MONTGOMERY"); + addKeyType(CKK_HKDF, "CKK_HKDF"); + + addKeyType(CKK_SHA512_224_HMAC, "CKK_SHA512_224_HMAC"); + addKeyType(CKK_SHA512_256_HMAC, "CKK_SHA512_256_HMAC"); + addKeyType(CKK_SHA512_T_HMAC, "CKK_SHA512_T_HMAC"); addKeyType(CKK_VENDOR_DEFINED, "CKK_VENDOR_DEFINED"); @@ -1040,6 +1185,7 @@ private static void addMGF(long id, String name) { addAttribute(CKA_TOKEN, "CKA_TOKEN"); addAttribute(CKA_PRIVATE, "CKA_PRIVATE"); addAttribute(CKA_LABEL, "CKA_LABEL"); + addAttribute(CKA_UNIQUE_ID, "CKA_UNIQUE_ID"); addAttribute(CKA_APPLICATION, "CKA_APPLICATION"); addAttribute(CKA_VALUE, "CKA_VALUE"); addAttribute(CKA_OBJECT_ID, "CKA_OBJECT_ID"); @@ -1154,6 +1300,24 @@ private static void addMGF(long id, String name) { addAttribute(CKA_SUPPORTED_CMS_ATTRIBUTES, "CKA_SUPPORTED_CMS_ATTRIBUTES"); addAttribute(CKA_ALLOWED_MECHANISMS, "CKA_ALLOWED_MECHANISMS"); + addAttribute(CKA_PROFILE_ID, "CKA_PROFILE_ID"); + addAttribute(CKA_X2RATCHET_BAG, "CKA_X2RATCHET_BAG"); + addAttribute(CKA_X2RATCHET_BAGSIZE, "CKA_X2RATCHET_BAGSIZE"); + addAttribute(CKA_X2RATCHET_BOBS1STMSG, "CKA_X2RATCHET_BOBS1STMSG"); + addAttribute(CKA_X2RATCHET_CKR, "CKA_X2RATCHET_CKR"); + addAttribute(CKA_X2RATCHET_CKS, "CKA_X2RATCHET_CKS"); + addAttribute(CKA_X2RATCHET_DHP, "CKA_X2RATCHET_DHP"); + addAttribute(CKA_X2RATCHET_DHR, "CKA_X2RATCHET_DHR"); + addAttribute(CKA_X2RATCHET_DHS, "CKA_X2RATCHET_DHS"); + addAttribute(CKA_X2RATCHET_HKR, "CKA_X2RATCHET_HKR"); + addAttribute(CKA_X2RATCHET_HKS, "CKA_X2RATCHET_HKS"); + addAttribute(CKA_X2RATCHET_ISALICE, "CKA_X2RATCHET_ISALICE"); + addAttribute(CKA_X2RATCHET_NHKR, "CKA_X2RATCHET_NHKR"); + addAttribute(CKA_X2RATCHET_NHKS, "CKA_X2RATCHET_NHKS"); + addAttribute(CKA_X2RATCHET_NR, "CKA_X2RATCHET_NR"); + addAttribute(CKA_X2RATCHET_NS, "CKA_X2RATCHET_NS"); + addAttribute(CKA_X2RATCHET_PNS, "CKA_X2RATCHET_PNS"); + addAttribute(CKA_X2RATCHET_RK, "CKA_X2RATCHET_RK"); addAttribute(CKA_VENDOR_DEFINED, "CKA_VENDOR_DEFINED"); addAttribute(CKA_NETSCAPE_DB, "CKA_NETSCAPE_DB"); @@ -1172,6 +1336,9 @@ private static void addMGF(long id, String name) { addObjectClass(CKO_SECRET_KEY, "CKO_SECRET_KEY"); addObjectClass(CKO_HW_FEATURE, "CKO_HW_FEATURE"); addObjectClass(CKO_DOMAIN_PARAMETERS, "CKO_DOMAIN_PARAMETERS"); + addObjectClass(CKO_MECHANISM, "CKO_MECHANISM"); + addObjectClass(CKO_OTP_KEY, "CKO_OTP_KEY"); + addObjectClass(CKO_PROFILE, "CKO_PROFILE"); addObjectClass(CKO_VENDOR_DEFINED, "CKO_VENDOR_DEFINED"); addObjectClass(PCKO_ANY, "*"); @@ -1181,6 +1348,10 @@ private static void addMGF(long id, String name) { addMGF(CKG_MGF1_SHA384, "CKG_MGF1_SHA384"); addMGF(CKG_MGF1_SHA512, "CKG_MGF1_SHA512"); addMGF(CKG_MGF1_SHA224, "CKG_MGF1_SHA224"); + addMGF(CKG_MGF1_SHA3_224, "CKG_MGF1_SHA3_224"); + addMGF(CKG_MGF1_SHA3_256, "CKG_MGF1_SHA3_256"); + addMGF(CKG_MGF1_SHA3_384, "CKG_MGF1_SHA3_384"); + addMGF(CKG_MGF1_SHA3_512, "CKG_MGF1_SHA3_512"); } } diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java index f36b0534083..8746192098a 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 2002 Graz University of Technology. All rights reserved. @@ -48,7 +48,7 @@ package sun.security.pkcs11.wrapper; /** - * This interface holds constants of the PKCS#11 v2.11 standard. + * This interface holds constants of the PKCS#11 v3.00 standard. * This is mainly the content of the 'pkcs11t.h' header file. * * Mapping of primitiv data types to Java types: @@ -62,11 +62,15 @@ * CK_ULONG ...................................... long * CK_LONG ....................................... long * CK_FLAGS ...................................... long + * CK_BYTE_PTR ................................... byte[] + * CK_CHAR_PTR ................................... char[] + * CK_UTF8CHAR_PTR ............................... char[] + * CK_ULONG_PTR .................................. long[] + * CK_VOID_PTR ................................... Object[] * CK_NOTIFICATION ............................... long * CK_SLOT_ID .................................... long * CK_SESSION_HANDLE ............................. long * CK_USER_TYPE .................................. long - * CK_SESSION_HANDLE ............................. long * CK_STATE ...................................... long * CK_OBJECT_HANDLE .............................. long * CK_OBJECT_CLASS ............................... long @@ -74,21 +78,27 @@ * CK_KEY_TYPE ................................... long * CK_CERTIFICATE_TYPE ........................... long * CK_ATTRIBUTE_TYPE ............................. long - * CK_VOID_PTR ................................... Object[] - * CK_BYTE_PTR ................................... byte[] - * CK_CHAR_PTR ................................... char[] - * CK_UTF8CHAR_PTR ............................... char[] * CK_MECHANISM_TYPE ............................. long * CK_RV ......................................... long - * CK_RSA_PKCS_OAEP_MGF_TYPE ..................... long + * CK_RSA_PKCS_MGF_TYPE .......................... long * CK_RSA_PKCS_OAEP_SOURCE_TYPE .................. long + * CK_EC_KDF_TYPE ................................ long + * CK_X9_42_DH_KDF_TYPE .......................... long * CK_RC2_PARAMS ................................. long * CK_MAC_GENERAL_PARAMS ......................... long * CK_EXTRACT_PARAMS ............................. long * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE .... long * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE .............. long - * CK_EC_KDF_TYPE ................................ long - * CK_X9_42_DH_KDF_TYPE .......................... long + * CK_OTP_PARAM_TYPE / CK_PARAM_TYPE ............. long + * CK_GENERATOR_FUNCTION ......................... long + * CK_JAVA_MIDP_SECURITY_DOMAIN .................. long + * CK_CERTIFICATE_CATEGORY ....................... long + * CK_PROFILE_ID ................................. long + * CK_PRF_DATA_TYPE .............................. long + * CK_SP800_108_DKM_LENGTH_METHOD ................ long + * CK_X3DH_KDF_TYPE .............................. long + * CK_X2RATCHET_KDF_TYPE ......................... long + * CK_XEDDSA_HASH_TYPE ........................... long * * * @author Karl Scheibelhofer @@ -201,16 +211,30 @@ public interface PKCS11Constants { public static final long CKO_SECRET_KEY = 0x00000004L; public static final long CKO_HW_FEATURE = 0x00000005L; public static final long CKO_DOMAIN_PARAMETERS = 0x00000006L; + public static final long CKO_MECHANISM = 0x00000007L; + public static final long CKO_OTP_KEY = 0x00000008L; + public static final long CKO_PROFILE = 0x00000009L; + public static final long CKO_VENDOR_DEFINED = 0x80000000L; // pseudo object class ANY (for template manager) public static final long PCKO_ANY = 0x7FFFFF23L; + /* Uncomment when actually used + // Profile ID's + public static final long CKP_INVALID_ID = 0x00000000L; + public static final long CKP_BASELINE_PROVIDER = 0x00000001L; + public static final long CKP_EXTENDED_PROVIDER = 0x00000002L; + public static final long CKP_AUTHENTICATION_TOKEN = 0x00000003L; + public static final long CKP_PUBLIC_CERTIFICATES_TOKEN = 0x00000004L; + public static final long CKP_VENDOR_DEFINED = 0x80000000L; - /* The following hardware feature types are defined */ + // The following hardware feature types are defined public static final long CKH_MONOTONIC_COUNTER = 0x00000001L; public static final long CKH_CLOCK = 0x00000002L; + public static final long CKH_USER_INTERFACE = 0x00000003L; public static final long CKH_VENDOR_DEFINED = 0x80000000L; + */ /* the following key types are defined: */ public static final long CKK_RSA = 0x00000000L; @@ -259,7 +283,29 @@ public interface PKCS11Constants { public static final long CKK_GOSTR3410 = 0x00000030L; public static final long CKK_GOSTR3411 = 0x00000031L; public static final long CKK_GOST28147 = 0x00000032L; -; + public static final long CKK_CHACHA20 = 0x00000033L; + public static final long CKK_POLY1305 = 0x00000034L; + public static final long CKK_AES_XTS = 0x00000035L; + + public static final long CKK_SHA3_224_HMAC = 0x00000036L; + public static final long CKK_SHA3_256_HMAC = 0x00000037L; + public static final long CKK_SHA3_384_HMAC = 0x00000038L; + public static final long CKK_SHA3_512_HMAC = 0x00000039L; + + public static final long CKK_BLAKE2B_160_HMAC = 0x0000003aL; + public static final long CKK_BLAKE2B_256_HMAC = 0x0000003bL; + public static final long CKK_BLAKE2B_384_HMAC = 0x0000003cL; + public static final long CKK_BLAKE2B_512_HMAC = 0x0000003dL; + public static final long CKK_SALSA20 = 0x0000003eL; + public static final long CKK_X2RATCHET = 0x0000003fL; + public static final long CKK_EC_EDWARDS = 0x00000040L; + public static final long CKK_EC_MONTGOMERY = 0x00000041L; + public static final long CKK_HKDF = 0x00000042L; + + public static final long CKK_SHA512_224_HMAC = 0x00000043L; + public static final long CKK_SHA512_256_HMAC = 0x00000044L; + public static final long CKK_SHA512_T_HMAC = 0x00000045L; + public static final long CKK_VENDOR_DEFINED = 0x80000000L; // pseudo key type ANY (for template manager) @@ -271,9 +317,22 @@ public interface PKCS11Constants { public static final long PCKK_TLSRSAPREMASTER = 0x7FFFFF26L; public static final long PCKK_TLSMASTER = 0x7FFFFF27L; + /* Uncomment when actually used + public static final long CK_CERTIFICATE_CATEGORY_UNSPECIFIED = 0L; + public static final long CK_CERTIFICATE_CATEGORY_TOKEN_USER = 1L; + public static final long CK_CERTIFICATE_CATEGORY_AUTHORITY = 2L; + public static final long CK_CERTIFICATE_CATEGORY_OTHER_ENTITY = 3L; + + public static final long CK_SECURITY_DOMAIN_UNSPECIFIED = 0L; + public static final long CK_SECURITY_DOMAIN_MANUFACTURER = 1L; + public static final long CK_SECURITY_DOMAIN_OPERATOR = 2L; + public static final long CK_SECURITY_DOMAIN_THIRD_PARTY = 3L; + */ + /* The following certificate types are defined: */ public static final long CKC_X_509 = 0x00000000L; public static final long CKC_X_509_ATTR_CERT = 0x00000001L; + public static final long CKC_WTLS = 0x00000002L; public static final long CKC_VENDOR_DEFINED = 0x80000000L; /* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which @@ -281,11 +340,23 @@ public interface PKCS11Constants { */ public static final long CKF_ARRAY_ATTRIBUTE = 0x40000000L; + /* Uncomment when actually used + public static final long CK_OTP_FORMAT_DECIMAL = 0L; + public static final long CK_OTP_FORMAT_HEXADECIMAL = 1L; + public static final long CK_OTP_FORMAT_ALPHANUMERIC = 2L; + public static final long CK_OTP_FORMAT_BINARY = 3L; + + public static final long CK_OTP_PARAM_IGNORED = 0L; + public static final long CK_OTP_PARAM_OPTIONAL = 1L; + public static final long CK_OTP_PARAM_MANDATORY = 2L; + */ + /* The following attribute types are defined: */ public static final long CKA_CLASS = 0x00000000L; public static final long CKA_TOKEN = 0x00000001L; public static final long CKA_PRIVATE = 0x00000002L; public static final long CKA_LABEL = 0x00000003L; + public static final long CKA_UNIQUE_ID = 0x00000004L; public static final long CKA_APPLICATION = 0x00000010L; public static final long CKA_VALUE = 0x00000011L; public static final long CKA_OBJECT_ID = 0x00000012L; @@ -343,12 +414,10 @@ public interface PKCS11Constants { public static final long CKA_VALUE_BITS = 0x00000160L; public static final long CKA_VALUE_LEN = 0x00000161L; - public static final long CKA_EXTRACTABLE = 0x00000162L; public static final long CKA_LOCAL = 0x00000163L; public static final long CKA_NEVER_EXTRACTABLE = 0x00000164L; public static final long CKA_ALWAYS_SENSITIVE = 0x00000165L; - public static final long CKA_KEY_GEN_MECHANISM = 0x00000166L; public static final long CKA_MODIFIABLE = 0x00000170L; @@ -406,6 +475,25 @@ public interface PKCS11Constants { public static final long CKA_SUPPORTED_CMS_ATTRIBUTES = 0x00000503L; public static final long CKA_ALLOWED_MECHANISMS = (CKF_ARRAY_ATTRIBUTE|0x00000600L); + public static final long CKA_PROFILE_ID = 0x00000601L; + public static final long CKA_X2RATCHET_BAG = 0x00000602L; + public static final long CKA_X2RATCHET_BAGSIZE = 0x00000603L; + public static final long CKA_X2RATCHET_BOBS1STMSG = 0x00000604L; + public static final long CKA_X2RATCHET_CKR = 0x00000605L; + public static final long CKA_X2RATCHET_CKS = 0x00000606L; + public static final long CKA_X2RATCHET_DHP = 0x00000607L; + public static final long CKA_X2RATCHET_DHR = 0x00000608L; + public static final long CKA_X2RATCHET_DHS = 0x00000609L; + public static final long CKA_X2RATCHET_HKR = 0x0000060aL; + public static final long CKA_X2RATCHET_HKS = 0x0000060bL; + public static final long CKA_X2RATCHET_ISALICE = 0x0000060cL; + public static final long CKA_X2RATCHET_NHKR = 0x0000060dL; + public static final long CKA_X2RATCHET_NHKS = 0x0000060eL; + public static final long CKA_X2RATCHET_NR = 0x0000060fL; + public static final long CKA_X2RATCHET_NS = 0x00000610L; + public static final long CKA_X2RATCHET_PNS = 0x00000611L; + public static final long CKA_X2RATCHET_RK = 0x00000612L; + public static final long CKA_VENDOR_DEFINED = 0x80000000L; /* the following mechanism types are defined: */ @@ -435,6 +523,10 @@ public interface PKCS11Constants { public static final long CKM_DSA_SHA256 = 0x00000014L; public static final long CKM_DSA_SHA384 = 0x00000015L; public static final long CKM_DSA_SHA512 = 0x00000016L; + public static final long CKM_DSA_SHA3_224 = 0x00000018L; + public static final long CKM_DSA_SHA3_256 = 0x00000019L; + public static final long CKM_DSA_SHA3_384 = 0x0000001AL; + public static final long CKM_DSA_SHA3_512 = 0x0000001BL; public static final long CKM_DH_PKCS_KEY_PAIR_GEN = 0x00000020L; public static final long CKM_DH_PKCS_DERIVE = 0x00000021L; @@ -468,6 +560,15 @@ public interface PKCS11Constants { public static final long CKM_SHA512_T_HMAC_GENERAL = 0x00000052L; public static final long CKM_SHA512_T_KEY_DERIVATION = 0x00000053L; + public static final long CKM_SHA3_256_RSA_PKCS = 0x00000060L; + public static final long CKM_SHA3_384_RSA_PKCS = 0x00000061L; + public static final long CKM_SHA3_512_RSA_PKCS = 0x00000062L; + public static final long CKM_SHA3_256_RSA_PKCS_PSS = 0x00000063L; + public static final long CKM_SHA3_384_RSA_PKCS_PSS = 0x00000064L; + public static final long CKM_SHA3_512_RSA_PKCS_PSS = 0x00000065L; + public static final long CKM_SHA3_224_RSA_PKCS = 0x00000066L; + public static final long CKM_SHA3_224_RSA_PKCS_PSS = 0x00000067L; + public static final long CKM_RC2_KEY_GEN = 0x00000100L; public static final long CKM_RC2_ECB = 0x00000101L; public static final long CKM_RC2_CBC = 0x00000102L; @@ -551,6 +652,23 @@ public interface PKCS11Constants { public static final long CKM_ACTI = 0x000002A0L; public static final long CKM_ACTI_KEY_GEN = 0x000002A1L; + public static final long CKM_SHA3_256 = 0x000002B0L; + public static final long CKM_SHA3_256_HMAC = 0x000002B1L; + public static final long CKM_SHA3_256_HMAC_GENERAL = 0x000002B2L; + public static final long CKM_SHA3_256_KEY_GEN = 0x000002B3L; + public static final long CKM_SHA3_224 = 0x000002B5L; + public static final long CKM_SHA3_224_HMAC = 0x000002B6L; + public static final long CKM_SHA3_224_HMAC_GENERAL = 0x000002B7L; + public static final long CKM_SHA3_224_KEY_GEN = 0x000002B8L; + public static final long CKM_SHA3_384 = 0x000002C0L; + public static final long CKM_SHA3_384_HMAC = 0x000002C1L; + public static final long CKM_SHA3_384_HMAC_GENERAL = 0x000002C2L; + public static final long CKM_SHA3_384_KEY_GEN = 0x000002C3L; + public static final long CKM_SHA3_512 = 0x000002D0L; + public static final long CKM_SHA3_512_HMAC = 0x000002D1L; + public static final long CKM_SHA3_512_HMAC_GENERAL = 0x000002D2L; + public static final long CKM_SHA3_512_KEY_GEN = 0x000002D3L; + public static final long CKM_CAST_KEY_GEN = 0x00000300L; public static final long CKM_CAST_ECB = 0x00000301L; public static final long CKM_CAST_CBC = 0x00000302L; @@ -611,19 +729,26 @@ public interface PKCS11Constants { public static final long CKM_MD5_KEY_DERIVATION = 0x00000390L; public static final long CKM_MD2_KEY_DERIVATION = 0x00000391L; public static final long CKM_SHA1_KEY_DERIVATION = 0x00000392L; - public static final long CKM_SHA256_KEY_DERIVATION = 0x00000393L; public static final long CKM_SHA384_KEY_DERIVATION = 0x00000394L; public static final long CKM_SHA512_KEY_DERIVATION = 0x00000395L; public static final long CKM_SHA224_KEY_DERIVATION = 0x00000396L; + public static final long CKM_SHA3_256_KEY_DERIVATION = 0x00000397L; + public static final long CKM_SHA3_224_KEY_DERIVATION = 0x00000398L; + public static final long CKM_SHA3_384_KEY_DERIVATION = 0x00000399L; + public static final long CKM_SHA3_512_KEY_DERIVATION = 0x0000039AL; + public static final long CKM_SHAKE_128_KEY_DERIVATION = 0x0000039BL; + public static final long CKM_SHAKE_256_KEY_DERIVATION = 0x0000039CL; public static final long CKM_PBE_MD2_DES_CBC = 0x000003A0L; public static final long CKM_PBE_MD5_DES_CBC = 0x000003A1L; public static final long CKM_PBE_MD5_CAST_CBC = 0x000003A2L; public static final long CKM_PBE_MD5_CAST3_CBC = 0x000003A3L; - public static final long CKM_PBE_MD5_CAST5_CBC = 0x000003A4L; + public static final long CKM_PBE_MD5_CAST5_CBC /*deprecated*/ + = 0x000003A4L; public static final long CKM_PBE_MD5_CAST128_CBC = 0x000003A4L; - public static final long CKM_PBE_SHA1_CAST5_CBC = 0x000003A5L; + public static final long CKM_PBE_SHA1_CAST5_CBC /*deprecated*/ + = 0x000003A5L; public static final long CKM_PBE_SHA1_CAST128_CBC = 0x000003A5L; public static final long CKM_PBE_SHA1_RC4_128 = 0x000003A6L; public static final long CKM_PBE_SHA1_RC4_40 = 0x000003A7L; @@ -643,11 +768,12 @@ public interface PKCS11Constants { public static final long CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE = 0x000003D4L; public static final long CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE = 0x000003D5L; - public static final long CKM_TLS10_MAC_SERVER = 0x000003D6L; - public static final long CKM_TLS10_MAC_CLIENT = 0x000003D7L; + public static final long CKM_TLS10_MAC_SERVER /*removed in 3.00*/ + = 0x000003D6L; + public static final long CKM_TLS10_MAC_CLIENT /*removed in 3.00*/ + = 0x000003D7L; public static final long CKM_TLS12_MAC = 0x000003D8L; public static final long CKM_TLS12_KDF = 0x000003D9L; - public static final long CKM_TLS12_MASTER_KEY_DERIVE = 0x000003E0L; public static final long CKM_TLS12_KEY_AND_MAC_DERIVE = 0x000003E1L; public static final long CKM_TLS12_MASTER_KEY_DERIVE_DH = 0x000003E2L; @@ -717,6 +843,7 @@ public interface PKCS11Constants { public static final long CKM_ECDSA_KEY_PAIR_GEN /*deprecated*/ = 0x00001040L; public static final long CKM_EC_KEY_PAIR_GEN = 0x00001040L; + public static final long CKM_EC_KEY_PAIR_GEN_W_EXTRA_BITS = 0x0000140BL; public static final long CKM_ECDSA = 0x00001041L; public static final long CKM_ECDSA_SHA1 = 0x00001042L; @@ -724,6 +851,10 @@ public interface PKCS11Constants { public static final long CKM_ECDSA_SHA256 = 0x00001044L; public static final long CKM_ECDSA_SHA384 = 0x00001045L; public static final long CKM_ECDSA_SHA512 = 0x00001046L; + public static final long CKM_ECDSA_SHA3_224 = 0x00001047L; + public static final long CKM_ECDSA_SHA3_256 = 0x00001048L; + public static final long CKM_ECDSA_SHA3_384 = 0x00001049L; + public static final long CKM_ECDSA_SHA3_512 = 0x0000104AL; public static final long CKM_ECDH1_DERIVE = 0x00001050L; public static final long CKM_ECDH1_COFACTOR_DERIVE = 0x00001051L; @@ -732,6 +863,10 @@ public interface PKCS11Constants { public static final long CKM_ECDH_AES_KEY_WRAP = 0x00001053L; public static final long CKM_RSA_AES_KEY_WRAP = 0x00001054L; + public static final long CKM_EC_EDWARDS_KEY_PAIR_GEN = 0x00001055L; + public static final long CKM_EC_MONTGOMERY_KEY_PAIR_GEN = 0x00001056L; + public static final long CKM_EDDSA = 0x00001057L; + public static final long CKM_JUNIPER_KEY_GEN = 0x00001060L; public static final long CKM_JUNIPER_ECB128 = 0x00001061L; public static final long CKM_JUNIPER_CBC128 = 0x00001062L; @@ -740,6 +875,8 @@ public interface PKCS11Constants { public static final long CKM_JUNIPER_WRAP = 0x00001065L; public static final long CKM_FASTHASH = 0x00001070L; + public static final long CKM_AES_XTS = 0x00001071L; + public static final long CKM_AES_XTS_KEY_GEN = 0x00001072L; public static final long CKM_AES_KEY_GEN = 0x00001080L; public static final long CKM_AES_ECB = 0x00001081L; public static final long CKM_AES_CBC = 0x00001082L; @@ -784,23 +921,80 @@ public interface PKCS11Constants { public static final long CKM_GOST28147_MAC = 0x00001223L; public static final long CKM_GOST28147_KEY_WRAP = 0x00001224L; + public static final long CKM_CHACHA20_KEY_GEN = 0x00001225L; + public static final long CKM_CHACHA20 = 0x00001226L; + public static final long CKM_POLY1305_KEY_GEN = 0x00001227L; + public static final long CKM_POLY1305 = 0x00001228L; + public static final long CKM_DSA_PARAMETER_GEN = 0x00002000L; public static final long CKM_DH_PKCS_PARAMETER_GEN = 0x00002001L; public static final long CKM_X9_42_DH_PARAMETER_GEN = 0x00002002L; public static final long CKM_DSA_PROBABLISTIC_PARAMETER_GEN = 0x00002003L; public static final long CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN = 0x00002004L; + public static final long CKM_DSA_FIPS_G_GEN = 0x00002005L; public static final long CKM_AES_OFB = 0x00002104L; public static final long CKM_AES_CFB64 = 0x00002105L; public static final long CKM_AES_CFB8 = 0x00002106L; public static final long CKM_AES_CFB128 = 0x00002107L; public static final long CKM_AES_CFB1 = 0x00002108L; - public static final long CKM_AES_KEY_WRAP = 0x00002109L; - public static final long CKM_AES_KEY_WRAP_PAD = 0x0000210AL; + public static final long CKM_AES_KEY_WRAP /* WAS: 0x00001090 */ + = 0x00002109L; + public static final long CKM_AES_KEY_WRAP_PAD /* WAS: 0x00001091 */ + = 0x0000210AL; + public static final long CKM_AES_KEY_WRAP_KWP = 0x0000210BL; public static final long CKM_RSA_PKCS_TPM_1_1 = 0x00004001L; public static final long CKM_RSA_PKCS_OAEP_TPM_1_1 = 0x00004002L; + public static final long CKM_SHA_1_KEY_GEN = 0x00004003L; + public static final long CKM_SHA224_KEY_GEN = 0x00004004L; + public static final long CKM_SHA256_KEY_GEN = 0x00004005L; + public static final long CKM_SHA384_KEY_GEN = 0x00004006L; + public static final long CKM_SHA512_KEY_GEN = 0x00004007L; + public static final long CKM_SHA512_224_KEY_GEN = 0x00004008L; + public static final long CKM_SHA512_256_KEY_GEN = 0x00004009L; + public static final long CKM_SHA512_T_KEY_GEN = 0x0000400aL; + public static final long CKM_NULL = 0x0000400bL; + public static final long CKM_BLAKE2B_160 = 0x0000400cL; + public static final long CKM_BLAKE2B_160_HMAC = 0x0000400dL; + public static final long CKM_BLAKE2B_160_HMAC_GENERAL = 0x0000400eL; + public static final long CKM_BLAKE2B_160_KEY_DERIVE = 0x0000400fL; + public static final long CKM_BLAKE2B_160_KEY_GEN = 0x00004010L; + public static final long CKM_BLAKE2B_256 = 0x00004011L; + public static final long CKM_BLAKE2B_256_HMAC = 0x00004012L; + public static final long CKM_BLAKE2B_256_HMAC_GENERAL = 0x00004013L; + public static final long CKM_BLAKE2B_256_KEY_DERIVE = 0x00004014L; + public static final long CKM_BLAKE2B_256_KEY_GEN = 0x00004015L; + public static final long CKM_BLAKE2B_384 = 0x00004016L; + public static final long CKM_BLAKE2B_384_HMAC = 0x00004017L; + public static final long CKM_BLAKE2B_384_HMAC_GENERAL = 0x00004018L; + public static final long CKM_BLAKE2B_384_KEY_DERIVE = 0x00004019L; + public static final long CKM_BLAKE2B_384_KEY_GEN = 0x0000401aL; + public static final long CKM_BLAKE2B_512 = 0x0000401bL; + public static final long CKM_BLAKE2B_512_HMAC = 0x0000401cL; + public static final long CKM_BLAKE2B_512_HMAC_GENERAL = 0x0000401dL; + public static final long CKM_BLAKE2B_512_KEY_DERIVE = 0x0000401eL; + public static final long CKM_BLAKE2B_512_KEY_GEN = 0x0000401fL; + public static final long CKM_SALSA20 = 0x00004020L; + public static final long CKM_CHACHA20_POLY1305 = 0x00004021L; + public static final long CKM_SALSA20_POLY1305 = 0x00004022L; + public static final long CKM_X3DH_INITIALIZE = 0x00004023L; + public static final long CKM_X3DH_RESPOND = 0x00004024L; + public static final long CKM_X2RATCHET_INITIALIZE = 0x00004025L; + public static final long CKM_X2RATCHET_RESPOND = 0x00004026L; + public static final long CKM_X2RATCHET_ENCRYPT = 0x00004027L; + public static final long CKM_X2RATCHET_DECRYPT = 0x00004028L; + public static final long CKM_XEDDSA = 0x00004029L; + public static final long CKM_HKDF_DERIVE = 0x0000402aL; + public static final long CKM_HKDF_DATA = 0x0000402bL; + public static final long CKM_HKDF_KEY_GEN = 0x0000402cL; + public static final long CKM_SALSA20_KEY_GEN = 0x0000402dL; + + public static final long CKM_SP800_108_COUNTER_KDF = 0x000003acL; + public static final long CKM_SP800_108_FEEDBACK_KDF = 0x000003adL; + public static final long CKM_SP800_108_DOUBLE_PIPELINE_KDF = 0x000003aeL; + public static final long CKM_VENDOR_DEFINED = 0x80000000L; // NSS private @@ -813,6 +1007,13 @@ public interface PKCS11Constants { /* The flags specify whether or not a mechanism can be used for a * particular task */ public static final long CKF_HW = 0x00000001L; + public static final long CKF_MESSAGE_ENCRYPT = 0x00000002L; + public static final long CKF_MESSAGE_DECRYPT = 0x00000004L; + public static final long CKF_MESSAGE_SIGN = 0x00000008L; + public static final long CKF_MESSAGE_VERIFY = 0x00000010L; + public static final long CKF_MULTI_MESSAGE = 0x00000020L; + public static final long CKF_FIND_OBJECTS = 0x00000040L; + public static final long CKF_ENCRYPT = 0x00000100L; public static final long CKF_DECRYPT = 0x00000200L; public static final long CKF_DIGEST = 0x00000400L; @@ -832,13 +1033,15 @@ public interface PKCS11Constants { public static final long CKF_EC_F_P = 0x00100000L; public static final long CKF_EC_F_2M = 0x00200000L; public static final long CKF_EC_ECPARAMETERS = 0x00400000L; - public static final long CKF_EC_NAMEDCURVE = 0x00800000L; + public static final long CKF_EC_OID = 0x00400000L; + public static final long CKF_EC_NAMEDCURVE /*deprecated since 3.00*/ + = CKF_EC_OID; public static final long CKF_EC_UNCOMPRESS = 0x01000000L; public static final long CKF_EC_COMPRESS = 0x02000000L; + public static final long CKF_EC_CURVENAME = 0x04000000L; public static final long CKF_EXTENSION = 0x80000000L; - /* Identifies the return value of a Cryptoki function */ public static final long CKR_OK = 0x00000000L; public static final long CKR_CANCEL = 0x00000001L; @@ -867,6 +1070,7 @@ public interface PKCS11Constants { public static final long CKR_DEVICE_REMOVED = 0x00000032L; public static final long CKR_ENCRYPTED_DATA_INVALID = 0x00000040L; public static final long CKR_ENCRYPTED_DATA_LEN_RANGE = 0x00000041L; + public static final long CKR_AEAD_DECRYPT_FAILED = 0x00000042L; public static final long CKR_FUNCTION_CANCELED = 0x00000050L; public static final long CKR_FUNCTION_NOT_PARALLEL = 0x00000051L; @@ -959,9 +1163,15 @@ public interface PKCS11Constants { public static final long CKR_PIN_TOO_WEAK = 0x000001B8L; public static final long CKR_PUBLIC_KEY_INVALID = 0x000001B9L; public static final long CKR_FUNCTION_REJECTED = 0x00000200L; + public static final long CKR_TOKEN_RESOURCE_EXCEEDED = 0x00000201L; + public static final long CKR_OPERATION_CANCEL_FAILED = 0x00000202L; public static final long CKR_VENDOR_DEFINED = 0x80000000L; + /* Uncomment when actually used + public static final long CKF_END_OF_MESSAGE = 0x00000001L; + public static final long CKF_INTERFACE_FORK_SAFE = 0x00000001L; + */ /* flags: bit flags that provide capabilities of the slot * Bit Flag = Mask @@ -969,7 +1179,6 @@ public interface PKCS11Constants { public static final long CKF_LIBRARY_CANT_CREATE_OS_THREADS = 0x00000001L; public static final long CKF_OS_LOCKING_OK = 0x00000002L; - /* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */ public static final long CKF_DONT_BLOCK = 1L; @@ -979,16 +1188,20 @@ public interface PKCS11Constants { public static final long CKG_MGF1_SHA384 = 0x00000003L; public static final long CKG_MGF1_SHA512 = 0x00000004L; public static final long CKG_MGF1_SHA224 = 0x00000005L; + public static final long CKG_MGF1_SHA3_224 = 0x00000006L; + public static final long CKG_MGF1_SHA3_256 = 0x00000007L; + public static final long CKG_MGF1_SHA3_384 = 0x00000008L; + public static final long CKG_MGF1_SHA3_512 = 0x00000009L; /* The following encoding parameter sources are defined */ public static final long CKZ_DATA_SPECIFIED = 0x00000001L; - - /* the following EC Key Derivation Functions are defined */ + // the following EC Key Derivation Functions are defined public static final long CKD_NULL = 0x00000001L; public static final long CKD_SHA1_KDF = 0x00000002L; - /* the following X9.42 Diffie-Hellman Key Derivation Functions are defined */ + /* Uncomment when actually used + // the following X9.42 Diffie-Hellman Key Derivation Functions are defined public static final long CKD_SHA1_KDF_ASN1 = 0x00000003L; public static final long CKD_SHA1_KDF_CONCATENATE = 0x00000004L; public static final long CKD_SHA224_KDF = 0x00000005L; @@ -996,6 +1209,23 @@ public interface PKCS11Constants { public static final long CKD_SHA384_KDF = 0x00000007L; public static final long CKD_SHA512_KDF = 0x00000008L; public static final long CKD_CPDIVERSIFY_KDF = 0x00000009L; + public static final long CKD_SHA3_224_KDF = 0x0000000AL; + public static final long CKD_SHA3_256_KDF = 0x0000000BL; + public static final long CKD_SHA3_384_KDF = 0x0000000CL; + public static final long CKD_SHA3_512_KDF = 0x0000000DL; + public static final long CKD_SHA1_KDF_SP800 = 0x0000000EL; + public static final long CKD_SHA224_KDF_SP800 = 0x0000000FL; + public static final long CKD_SHA256_KDF_SP800 = 0x00000010L; + public static final long CKD_SHA384_KDF_SP800 = 0x00000011L; + public static final long CKD_SHA512_KDF_SP800 = 0x00000012L; + public static final long CKD_SHA3_224_KDF_SP800 = 0x00000013L; + public static final long CKD_SHA3_256_KDF_SP800 = 0x00000014L; + public static final long CKD_SHA3_384_KDF_SP800 = 0x00000015L; + public static final long CKD_SHA3_512_KDF_SP800 = 0x00000016L; + public static final long CKD_BLAKE2B_160_KDF = 0x00000017L; + public static final long CKD_BLAKE2B_256_KDF = 0x00000018L; + public static final long CKD_BLAKE2B_384_KDF = 0x00000019L; + public static final long CKD_BLAKE2B_512_KDF = 0x0000001aL; public static final long CKP_PKCS5_PBKD2_HMAC_SHA1 = 0x00000001L; public static final long CKP_PKCS5_PBKD2_HMAC_GOSTR3411 = 0x00000002L; @@ -1024,33 +1254,53 @@ public interface PKCS11Constants { public static final long CKF_EXCLUDE_PIN = 0x00000010L; public static final long CKF_USER_FRIENDLY_OTP = 0x00000020L; + public static final long CKG_NO_GENERATE = 0x00000000L; + public static final long CKG_GENERATE = 0x00000001L; + public static final long CKG_GENERATE_COUNTER = 0x00000002L; + public static final long CKG_GENERATE_RANDOM = 0x00000003L; + + public static final long CK_SP800_108_ITERATION_VARIABLE = 0x00000001L; + public static final long CK_SP800_108_OPTIONAL_COUNTER = 0x00000002L; + public static final long CK_SP800_108_DKM_LENGTH = 0x00000003L; + public static final long CK_SP800_108_BYTE_ARRAY = 0x00000004L; + public static final long CK_SP800_108_DKM_LENGTH_SUM_OF_KEYS + = 0x00000001L; + public static final long CK_SP800_108_DKM_LENGTH_SUM_OF_SEGMENTS + = 0x00000002L; + + public static final long CKF_HKDF_SALT_NULL = 0x00000001L; + public static final long CKF_HKDF_SALT_DATA = 0x00000002L; + public static final long CKF_HKDF_SALT_KEY = 0x00000004L; + */ + // private NSS attribute (for DSA and DH private keys) public static final long CKA_NETSCAPE_DB = 0xD5A0DB00L; // base number of NSS private attributes - public static final long CKA_NETSCAPE_BASE = 0x80000000L + 0x4E534350L; + public static final long CKA_NETSCAPE_BASE /*0x80000000L + 0x4E534350L*/ + = 0xCE534350L; // object type for NSS trust - public static final long CKO_NETSCAPE_TRUST = CKA_NETSCAPE_BASE + 3; + public static final long CKO_NETSCAPE_TRUST = 0xCE534353L; // base number for NSS trust attributes - public static final long CKA_NETSCAPE_TRUST_BASE = CKA_NETSCAPE_BASE + 0x2000; + public static final long CKA_NETSCAPE_TRUST_BASE = 0xCE536350L; // attributes for NSS trust - public static final long CKA_NETSCAPE_TRUST_SERVER_AUTH = CKA_NETSCAPE_TRUST_BASE + 8; - public static final long CKA_NETSCAPE_TRUST_CLIENT_AUTH = CKA_NETSCAPE_TRUST_BASE + 9; - public static final long CKA_NETSCAPE_TRUST_CODE_SIGNING = CKA_NETSCAPE_TRUST_BASE + 10; - public static final long CKA_NETSCAPE_TRUST_EMAIL_PROTECTION = CKA_NETSCAPE_TRUST_BASE + 11; - public static final long CKA_NETSCAPE_CERT_SHA1_HASH = CKA_NETSCAPE_TRUST_BASE + 100; - public static final long CKA_NETSCAPE_CERT_MD5_HASH = CKA_NETSCAPE_TRUST_BASE + 101; + public static final long CKA_NETSCAPE_TRUST_SERVER_AUTH = 0xCE536358L; + public static final long CKA_NETSCAPE_TRUST_CLIENT_AUTH = 0xCE536359L; + public static final long CKA_NETSCAPE_TRUST_CODE_SIGNING = 0xCE53635AL; + public static final long CKA_NETSCAPE_TRUST_EMAIL_PROTECTION = 0xCE53635BL; + public static final long CKA_NETSCAPE_CERT_SHA1_HASH = 0xCE5363B4L; + public static final long CKA_NETSCAPE_CERT_MD5_HASH = 0xCE5363B5L; // trust values for each of the NSS trust attributes - public static final long CKT_NETSCAPE_TRUSTED = CKA_NETSCAPE_BASE + 1; - public static final long CKT_NETSCAPE_TRUSTED_DELEGATOR = CKA_NETSCAPE_BASE + 2; - public static final long CKT_NETSCAPE_UNTRUSTED = CKA_NETSCAPE_BASE + 3; - public static final long CKT_NETSCAPE_MUST_VERIFY = CKA_NETSCAPE_BASE + 4; - public static final long CKT_NETSCAPE_TRUST_UNKNOWN = CKA_NETSCAPE_BASE + 5; /* default */ - public static final long CKT_NETSCAPE_VALID = CKA_NETSCAPE_BASE + 10; - public static final long CKT_NETSCAPE_VALID_DELEGATOR = CKA_NETSCAPE_BASE + 11; - + public static final long CKT_NETSCAPE_TRUSTED = 0xCE534351L; + public static final long CKT_NETSCAPE_TRUSTED_DELEGATOR = 0xCE534352L; + public static final long CKT_NETSCAPE_UNTRUSTED = 0xCE534353L; + public static final long CKT_NETSCAPE_MUST_VERIFY = 0xCE534354L; + public static final long CKT_NETSCAPE_TRUST_UNKNOWN /* default */ + = 0xCE534355L; + public static final long CKT_NETSCAPE_VALID = 0xCE53435AL; + public static final long CKT_NETSCAPE_VALID_DELEGATOR = 0xCE53435BL; } diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Exception.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Exception.java index 8791b4b84d8..271ded6cc2f 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Exception.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Exception.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 2002 Graz University of Technology. All rights reserved. @@ -48,7 +48,7 @@ package sun.security.pkcs11.wrapper; import java.util.*; - +import static sun.security.pkcs11.wrapper.PKCS11Constants.*; /** * This is the superclass of all checked exceptions used by this package. An @@ -73,101 +73,105 @@ public class PKCS11Exception extends Exception { private static final Map errorMap; static { - int[] errorCodes = new int[] { - 0x00000000, - 0x00000001, - 0x00000002, - 0x00000003, - 0x00000005, - 0x00000006, - 0x00000007, - 0x00000008, - 0x00000009, - 0x0000000A, - 0x00000010, - 0x00000011, - 0x00000012, - 0x00000013, - 0x0000001B, - 0x00000020, - 0x00000021, - 0x00000030, - 0x00000031, - 0x00000032, - 0x00000040, - 0x00000041, - 0x00000050, - 0x00000051, - 0x00000054, - 0x00000060, - 0x00000062, - 0x00000063, - 0x00000064, - 0x00000065, - 0x00000066, - 0x00000067, - 0x00000068, - 0x00000069, - 0x0000006A, - 0x00000070, - 0x00000071, - 0x00000082, - 0x00000090, - 0x00000091, - 0x000000A0, - 0x000000A1, - 0x000000A2, - 0x000000A3, - 0x000000A4, - 0x000000B0, - 0x000000B1, - 0x000000B3, - 0x000000B4, - 0x000000B5, - 0x000000B6, - 0x000000B7, - 0x000000B8, - 0x000000C0, - 0x000000C1, - 0x000000D0, - 0x000000D1, - 0x000000E0, - 0x000000E1, - 0x000000E2, - 0x000000F0, - 0x000000F1, - 0x000000F2, - 0x00000100, - 0x00000101, - 0x00000102, - 0x00000103, - 0x00000104, - 0x00000105, - 0x00000110, - 0x00000112, - 0x00000113, - 0x00000114, - 0x00000115, - 0x00000120, - 0x00000121, - 0x00000130, - 0x00000150, - 0x00000160, - 0x00000170, - 0x00000180, - 0x00000190, - 0x00000191, - 0x000001A0, - 0x000001A1, - 0x000001B0, - 0x000001B1, - 0x000001B5, - 0x000001B6, - 0x000001B7, - 0x000001B8, - 0x000001B9, - 0x00000200, - 0x80000000, + long[] errorCodes = new long[] { + CKR_OK, + CKR_CANCEL, + CKR_HOST_MEMORY, + CKR_SLOT_ID_INVALID, + CKR_GENERAL_ERROR, + CKR_FUNCTION_FAILED, + CKR_ARGUMENTS_BAD, + CKR_NO_EVENT, + CKR_NEED_TO_CREATE_THREADS, + CKR_CANT_LOCK, + CKR_ATTRIBUTE_READ_ONLY, + CKR_ATTRIBUTE_SENSITIVE, + CKR_ATTRIBUTE_TYPE_INVALID, + CKR_ATTRIBUTE_VALUE_INVALID, + CKR_ACTION_PROHIBITED, + CKR_DATA_INVALID, + CKR_DATA_LEN_RANGE, + CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, + CKR_DEVICE_REMOVED, + CKR_ENCRYPTED_DATA_INVALID, + CKR_ENCRYPTED_DATA_LEN_RANGE, + CKR_AEAD_DECRYPT_FAILED, + CKR_FUNCTION_CANCELED, + CKR_FUNCTION_NOT_PARALLEL, + CKR_FUNCTION_NOT_SUPPORTED, + CKR_KEY_HANDLE_INVALID, + CKR_KEY_SIZE_RANGE, + CKR_KEY_TYPE_INCONSISTENT, + CKR_KEY_NOT_NEEDED, + CKR_KEY_CHANGED, + CKR_KEY_NEEDED, + CKR_KEY_INDIGESTIBLE, + CKR_KEY_FUNCTION_NOT_PERMITTED, + CKR_KEY_NOT_WRAPPABLE, + CKR_KEY_UNEXTRACTABLE, + CKR_MECHANISM_INVALID, + CKR_MECHANISM_PARAM_INVALID, + CKR_OBJECT_HANDLE_INVALID, + CKR_OPERATION_ACTIVE, + CKR_OPERATION_NOT_INITIALIZED, + CKR_PIN_INCORRECT, + CKR_PIN_INVALID, + CKR_PIN_LEN_RANGE, + CKR_PIN_EXPIRED, + CKR_PIN_LOCKED, + CKR_SESSION_CLOSED, + CKR_SESSION_COUNT, + CKR_SESSION_HANDLE_INVALID, + CKR_SESSION_PARALLEL_NOT_SUPPORTED, + CKR_SESSION_READ_ONLY, + CKR_SESSION_EXISTS, + CKR_SESSION_READ_ONLY_EXISTS, + CKR_SESSION_READ_WRITE_SO_EXISTS, + CKR_SIGNATURE_INVALID, + CKR_SIGNATURE_LEN_RANGE, + CKR_TEMPLATE_INCOMPLETE, + CKR_TEMPLATE_INCONSISTENT, + CKR_TOKEN_NOT_PRESENT, + CKR_TOKEN_NOT_RECOGNIZED, + CKR_TOKEN_WRITE_PROTECTED, + CKR_UNWRAPPING_KEY_HANDLE_INVALID, + CKR_UNWRAPPING_KEY_SIZE_RANGE, + CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, + CKR_USER_ALREADY_LOGGED_IN, + CKR_USER_NOT_LOGGED_IN, + CKR_USER_PIN_NOT_INITIALIZED, + CKR_USER_TYPE_INVALID, + CKR_USER_ANOTHER_ALREADY_LOGGED_IN, + CKR_USER_TOO_MANY_TYPES, + CKR_WRAPPED_KEY_INVALID, + CKR_WRAPPED_KEY_LEN_RANGE, + CKR_WRAPPING_KEY_HANDLE_INVALID, + CKR_WRAPPING_KEY_SIZE_RANGE, + CKR_WRAPPING_KEY_TYPE_INCONSISTENT, + CKR_RANDOM_SEED_NOT_SUPPORTED, + CKR_RANDOM_NO_RNG, + CKR_DOMAIN_PARAMS_INVALID, + CKR_CURVE_NOT_SUPPORTED, + CKR_BUFFER_TOO_SMALL, + CKR_SAVED_STATE_INVALID, + CKR_INFORMATION_SENSITIVE, + CKR_STATE_UNSAVEABLE, + CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_CRYPTOKI_ALREADY_INITIALIZED, + CKR_MUTEX_BAD, + CKR_MUTEX_NOT_LOCKED, + CKR_NEW_PIN_MODE, + CKR_NEXT_OTP, + CKR_EXCEEDED_MAX_ITERATIONS, + CKR_FIPS_SELF_TEST_FAILED, + CKR_LIBRARY_LOAD_FAILED, + CKR_PIN_TOO_WEAK, + CKR_PUBLIC_KEY_INVALID, + CKR_FUNCTION_REJECTED, + CKR_TOKEN_RESOURCE_EXCEEDED, + CKR_OPERATION_CANCEL_FAILED, + CKR_VENDOR_DEFINED, }; String[] errorMessages = new String[] { "CKR_OK", @@ -192,6 +196,7 @@ public class PKCS11Exception extends Exception { "CKR_DEVICE_REMOVED", "CKR_ENCRYPTED_DATA_INVALID", "CKR_ENCRYPTED_DATA_LEN_RANGE", + "CKR_AEAD_DECRYPT_FAILED", "CKR_FUNCTION_CANCELED", "CKR_FUNCTION_NOT_PARALLEL", "CKR_FUNCTION_NOT_SUPPORTED", @@ -247,6 +252,7 @@ public class PKCS11Exception extends Exception { "CKR_RANDOM_SEED_NOT_SUPPORTED", "CKR_RANDOM_NO_RNG", "CKR_DOMAIN_PARAMS_INVALID", + "CKR_CURVE_NOT_SUPPORTED", "CKR_BUFFER_TOO_SMALL", "CKR_SAVED_STATE_INVALID", "CKR_INFORMATION_SENSITIVE", @@ -263,6 +269,8 @@ public class PKCS11Exception extends Exception { "CKR_PIN_TOO_WEAK", "CKR_PUBLIC_KEY_INVALID", "CKR_FUNCTION_REJECTED", + "CKR_TOKEN_RESOURCE_EXCEEDED", + "CKR_OPERATION_CANCEL_FAILED", "CKR_VENDOR_DEFINED", }; errorMap = new HashMap(); diff --git a/src/jdk.crypto.cryptoki/share/legal/pkcs11cryptotoken.md b/src/jdk.crypto.cryptoki/share/legal/pkcs11cryptotoken.md index bc366bb64e1..08d1e3c713d 100644 --- a/src/jdk.crypto.cryptoki/share/legal/pkcs11cryptotoken.md +++ b/src/jdk.crypto.cryptoki/share/legal/pkcs11cryptotoken.md @@ -1,32 +1,72 @@ -## OASIS PKCS #11 Cryptographic Token Interface v2.40 +## OASIS PKCS #11 Cryptographic Token Interface v3.0 ### OASIS PKCS #11 Cryptographic Token Interface License -``` - -Copyright (c) OASIS Open 2016. All Rights Reserved. - -All capitalized terms in the following text have the meanings assigned to them in the OASIS -Intellectual Property Rights Policy (the "OASIS IPR Policy"). The full Policy may be found at the -OASIS website: [http://www.oasis-open.org/policies-guidelines/ipr] - -This document and translations of it may be copied and furnished to others, and derivative works -that comment on or otherwise explain it or assist in its implementation may be prepared, copied, -published, and distributed, in whole or in part, without restriction of any kind, provided that -the above copyright notice and this section are included on all such copies and derivative works. -However, this document itself may not be modified in any way, including by removing the copyright -notice or references to OASIS, except as needed for the purpose of developing any document or -deliverable produced by an OASIS Technical Committee (in which case the rules applicable to -copyrights, as set forth in the OASIS IPR Policy, must be followed) or as required to translate it -into languages other than English. - -The limited permissions granted above are perpetual and will not be revoked by OASIS or its -successors or assigns. - -This document and the information contained herein is provided on an "AS IS" basis and OASIS -DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE -USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY OWNERSHIP RIGHTS OR ANY IMPLIED WARRANTIES OF -MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. OASIS AND ITS MEMBERS WILL NOT BE LIABLE FOR -ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THIS DOCUMENT OR -ANY PART THEREOF. - -``` +
    +
    +Copyright © OASIS Open 2020. All Rights Reserved.
    +
    +    All capitalized terms in the following text have the meanings
    +assigned to them in the OASIS Intellectual Property Rights Policy (the
    +"OASIS IPR Policy"). The full Policy may be found at the OASIS website:
    +[http://www.oasis-open.org/policies-guidelines/ipr]
    +
    +    This document and translations of it may be copied and furnished to
    +others, and derivative works that comment on or otherwise explain it or
    +assist in its implementation may be prepared, copied, published, and
    +distributed, in whole or in part, without restriction of any kind,
    +provided that the above copyright notice and this section are included
    +on all such copies and derivative works. However, this document itself
    +may not be modified in any way, including by removing the copyright
    +notice or references to OASIS, except as needed for the purpose of
    +developing any document or deliverable produced by an OASIS Technical
    +Committee (in which case the rules applicable to copyrights, as set
    +forth in the OASIS IPR Policy, must be followed) or as required to
    +translate it into languages other than English.
    +
    +    The limited permissions granted above are perpetual and will not be
    +revoked by OASIS or its successors or assigns.
    +
    +    This document and the information contained herein is provided on an
    +"AS IS" basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
    +INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
    +INFORMATION HEREIN WILL NOT INFRINGE ANY OWNERSHIP RIGHTS OR ANY IMPLIED
    +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. OASIS
    +AND ITS MEMBERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
    +CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THIS DOCUMENT OR ANY
    +PART THEREOF.
    +
    +    [OASIS requests that any OASIS Party or any other party that
    +believes it has patent claims that would necessarily be infringed by
    +implementations of this OASIS Standards Final Deliverable, to notify
    +OASIS TC Administrator and provide an indication of its willingness to
    +grant patent licenses to such patent claims in a manner consistent with
    +the IPR Mode of the OASIS Technical Committee that produced this
    +deliverable.]
    +
    +    [OASIS invites any party to contact the OASIS TC Administrator if it
    +is aware of a claim of ownership of any patent claims that would
    +necessarily be infringed by implementations of this OASIS Standards
    +Final Deliverable by a patent holder that is not willing to provide a
    +license to such patent claims in a manner consistent with the IPR Mode
    +of the OASIS Technical Committee that produced this OASIS Standards
    +Final Deliverable. OASIS may include such claims on its website, but
    +disclaims any obligation to do so.]
    +
    +    [OASIS takes no position regarding the validity or scope of any
    +intellectual property or other rights that might be claimed to pertain
    +to the implementation or use of the technology described in this OASIS
    +Standards Final Deliverable or the extent to which any license under
    +such rights might or might not be available; neither does it represent
    +that it has made any effort to identify any such rights. Information on
    +OASIS' procedures with respect to rights in any document or deliverable
    +produced by an OASIS Technical Committee can be found on the OASIS
    +website. Copies of claims of rights made available for publication and
    +any assurances of licenses to be made available, or the result of an
    +attempt made to obtain a general license or permission for the use of
    +such proprietary rights by implementers or users of this OASIS Standards
    +Final Deliverable, can be obtained from the OASIS TC Administrator.
    +OASIS makes no representation that any information or list of
    +intellectual property rights will at any time be complete, or that any
    +claims in such list are, in fact, Essential Claims.]
    +
    +
    diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11.h b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11.h index 6c84c8f3e9d..5b050def520 100644 --- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11.h +++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11.h @@ -1,14 +1,10 @@ -/* Copyright (c) OASIS Open 2016. All Rights Reserved./ - * /Distributed under the terms of the OASIS IPR Policy, +/* Copyright (c) OASIS Open 2016-2019. All Rights Reserved. + * Distributed under the terms of the OASIS IPR Policy, * [http://www.oasis-open.org/policies-guidelines/ipr], AS-IS, WITHOUT ANY * IMPLIED OR EXPRESS WARRANTY; there is no warranty of MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE or NONINFRINGEMENT of the rights of others. */ -/* Latest version of the specification: - * http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/pkcs11-base-v2.40.html - */ - #ifndef _PKCS11_H_ #define _PKCS11_H_ 1 @@ -29,8 +25,7 @@ extern "C" { * convention on packing is that structures should be 1-byte * aligned. * - * If you're using Microsoft Developer Studio 5.0 to produce - * Win32 stuff, this might be done by using the following + * If you're using Windows this might be done by using the following * preprocessor directive before including pkcs11.h or pkcs11t.h: * * #pragma pack(push, cryptoki, 1) @@ -40,13 +35,6 @@ extern "C" { * * #pragma pack(pop, cryptoki) * - * If you're using an earlier version of Microsoft Developer - * Studio to produce Win16 stuff, this might be done by using - * the following preprocessor directive before including - * pkcs11.h or pkcs11t.h: - * - * #pragma pack(1) - * * In a UNIX environment, you're on your own for this. You might * not need to do (or be able to do!) anything. * @@ -59,16 +47,10 @@ extern "C" { * * typedef CK_BYTE CK_PTR CK_BYTE_PTR; * - * If you're using Microsoft Developer Studio 5.0 to produce - * Win32 stuff, it might be defined by: + * If you're using windows, it might be defined by: * * #define CK_PTR * * - * If you're using an earlier version of Microsoft Developer - * Studio to produce Win16 stuff, it might be defined by: - * - * #define CK_PTR far * - * * In a typical UNIX environment, it might be defined by: * * #define CK_PTR * @@ -83,19 +65,12 @@ extern "C" { * CK_VOID_PTR pReserved * ); * - * If you're using Microsoft Developer Studio 5.0 to declare a - * function in a Win32 Cryptoki .dll, it might be defined by: + * If you're using Windows to declare a function in a Win32 cryptoki .dll, + * it might be defined by: * * #define CK_DECLARE_FUNCTION(returnType, name) \ * returnType __declspec(dllimport) name * - * If you're using an earlier version of Microsoft Developer - * Studio to declare a function in a Win16 Cryptoki .dll, it - * might be defined by: - * - * #define CK_DECLARE_FUNCTION(returnType, name) \ - * returnType __export _far _pascal name - * * In a UNIX environment, it might be defined by: * * #define CK_DECLARE_FUNCTION(returnType, name) \ @@ -120,19 +95,12 @@ extern "C" { * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args); * funcPtrType funcPtr; * - * If you're using Microsoft Developer Studio 5.0 to access + * If you're using Windows to access * functions in a Win32 Cryptoki .dll, in might be defined by: * * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ * returnType __declspec(dllimport) (* name) * - * If you're using an earlier version of Microsoft Developer - * Studio to access functions in a Win16 Cryptoki .dll, it might - * be defined by: - * - * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ - * returnType __export _far _pascal (* name) - * * In a UNIX environment, it might be defined by: * * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ @@ -153,18 +121,11 @@ extern "C" { * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args); * myCallbackType myCallback; * - * If you're using Microsoft Developer Studio 5.0 to do Win32 - * Cryptoki development, it might be defined by: + * If you're using Windows, it might be defined by: * * #define CK_CALLBACK_FUNCTION(returnType, name) \ * returnType (* name) * - * If you're using an earlier version of Microsoft Developer - * Studio to do Win16 development, it might be defined by: - * - * #define CK_CALLBACK_FUNCTION(returnType, name) \ - * returnType _far _pascal (* name) - * * In a UNIX environment, it might be defined by: * * #define CK_CALLBACK_FUNCTION(returnType, name) \ @@ -240,6 +201,22 @@ extern "C" { #define CK_PKCS11_FUNCTION_INFO(name) \ __PASTE(CK_,name) name; +/* Create the 3.0 Function list */ +struct CK_FUNCTION_LIST_3_0 { + + CK_VERSION version; /* Cryptoki version */ + +/* Pile all the function pointers into the CK_FUNCTION_LIST. */ +/* pkcs11f.h has all the information about the Cryptoki + * function prototypes. + */ +#include "pkcs11f.h" + +}; + +#define CK_PKCS11_2_0_ONLY 1 + +/* Continue to define the old CK_FUNCTION_LIST */ struct CK_FUNCTION_LIST { CK_VERSION version; /* Cryptoki version */ @@ -253,6 +230,7 @@ struct CK_FUNCTION_LIST { }; #undef CK_PKCS11_FUNCTION_INFO +#undef CK_PKCS11_2_0_ONLY #undef __PASTE @@ -263,3 +241,4 @@ struct CK_FUNCTION_LIST { #endif /* _PKCS11_H_ */ + diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11f.h b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11f.h index 87afebf2d44..0553c1dc73c 100644 --- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11f.h +++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11f.h @@ -1,4 +1,4 @@ -/* Copyright (c) OASIS Open 2016. All Rights Reserved./ +/* Copyright (c) OASIS Open 2016, 2019. All Rights Reserved./ * /Distributed under the terms of the OASIS IPR Policy, * [http://www.oasis-open.org/policies-guidelines/ipr], AS-IS, WITHOUT ANY * IMPLIED OR EXPRESS WARRANTY; there is no warranty of MERCHANTABILITY, FITNESS FOR A @@ -937,3 +937,261 @@ CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent) ); #endif +#ifndef CK_PKCS11_2_0_ONLY +/* C_GetInterfaceList returns all the interfaces supported by the module*/ +CK_PKCS11_FUNCTION_INFO(C_GetInterfaceList) +#ifdef CK_NEED_ARG_LIST +( + CK_INTERFACE_PTR pInterfacesList, /* returned interfaces */ + CK_ULONG_PTR pulCount /* number of interfaces returned */ +); +#endif + +/* C_GetInterface returns a specific interface from the module. */ +CK_PKCS11_FUNCTION_INFO(C_GetInterface) +#ifdef CK_NEED_ARG_LIST +( + CK_UTF8CHAR_PTR pInterfaceName, /* name of the interface */ + CK_VERSION_PTR pVersion, /* version of the interface */ + CK_INTERFACE_PTR_PTR ppInterface, /* returned interface */ + CK_FLAGS flags /* flags controlling the semantics + * of the interface */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_LoginUser) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_USER_TYPE userType, /* the user type */ + CK_UTF8CHAR_PTR pPin, /* the user's PIN */ + CK_ULONG ulPinLen, /* the length of the PIN */ + CK_UTF8CHAR_PTR pUsername, /* the user's name */ + CK_ULONG ulUsernameLen /*the length of the user's name */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_SessionCancel) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_FLAGS flags /* flags control which sessions are cancelled */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_MessageEncryptInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */ + CK_OBJECT_HANDLE hKey /* handle of encryption key */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_EncryptMessage) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_VOID_PTR pParameter, /* message specific parameter */ + CK_ULONG ulParameterLen, /* length of message specific parameter */ + CK_BYTE_PTR pAssociatedData, /* AEAD Associated data */ + CK_ULONG ulAssociatedDataLen, /* AEAD Associated data length */ + CK_BYTE_PTR pPlaintext, /* plain text */ + CK_ULONG ulPlaintextLen, /* plain text length */ + CK_BYTE_PTR pCiphertext, /* gets cipher text */ + CK_ULONG_PTR pulCiphertextLen /* gets cipher text length */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_EncryptMessageBegin) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_VOID_PTR pParameter, /* message specific parameter */ + CK_ULONG ulParameterLen, /* length of message specific parameter */ + CK_BYTE_PTR pAssociatedData, /* AEAD Associated data */ + CK_ULONG ulAssociatedDataLen /* AEAD Associated data length */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_EncryptMessageNext) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_VOID_PTR pParameter, /* message specific parameter */ + CK_ULONG ulParameterLen, /* length of message specific parameter */ + CK_BYTE_PTR pPlaintextPart, /* plain text */ + CK_ULONG ulPlaintextPartLen, /* plain text length */ + CK_BYTE_PTR pCiphertextPart, /* gets cipher text */ + CK_ULONG_PTR pulCiphertextPartLen, /* gets cipher text length */ + CK_FLAGS flags /* multi mode flag */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_MessageEncryptFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_MessageDecryptInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */ + CK_OBJECT_HANDLE hKey /* handle of decryption key */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_DecryptMessage) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_VOID_PTR pParameter, /* message specific parameter */ + CK_ULONG ulParameterLen, /* length of message specific parameter */ + CK_BYTE_PTR pAssociatedData, /* AEAD Associated data */ + CK_ULONG ulAssociatedDataLen, /* AEAD Associated data length */ + CK_BYTE_PTR pCiphertext, /* cipher text */ + CK_ULONG ulCiphertextLen, /* cipher text length */ + CK_BYTE_PTR pPlaintext, /* gets plain text */ + CK_ULONG_PTR pulPlaintextLen /* gets plain text length */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_DecryptMessageBegin) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_VOID_PTR pParameter, /* message specific parameter */ + CK_ULONG ulParameterLen, /* length of message specific parameter */ + CK_BYTE_PTR pAssociatedData, /* AEAD Associated data */ + CK_ULONG ulAssociatedDataLen /* AEAD Associated data length */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_DecryptMessageNext) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_VOID_PTR pParameter, /* message specific parameter */ + CK_ULONG ulParameterLen, /* length of message specific parameter */ + CK_BYTE_PTR pCiphertextPart, /* cipher text */ + CK_ULONG ulCiphertextPartLen, /* cipher text length */ + CK_BYTE_PTR pPlaintextPart, /* gets plain text */ + CK_ULONG_PTR pulPlaintextPartLen, /* gets plain text length */ + CK_FLAGS flags /* multi mode flag */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_MessageDecryptFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_MessageSignInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the signing mechanism */ + CK_OBJECT_HANDLE hKey /* handle of signing key */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_SignMessage) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_VOID_PTR pParameter, /* message specific parameter */ + CK_ULONG ulParameterLen, /* length of message specific parameter */ + CK_BYTE_PTR pData, /* data to sign */ + CK_ULONG ulDataLen, /* data to sign length */ + CK_BYTE_PTR pSignature, /* gets signature */ + CK_ULONG_PTR pulSignatureLen /* gets signature length */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_SignMessageBegin) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_VOID_PTR pParameter, /* message specific parameter */ + CK_ULONG ulParameterLen /* length of message specific parameter */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_SignMessageNext) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_VOID_PTR pParameter, /* message specific parameter */ + CK_ULONG ulParameterLen, /* length of message specific parameter */ + CK_BYTE_PTR pData, /* data to sign */ + CK_ULONG ulDataLen, /* data to sign length */ + CK_BYTE_PTR pSignature, /* gets signature */ + CK_ULONG_PTR pulSignatureLen /* gets signature length */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_MessageSignFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_MessageVerifyInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the signing mechanism */ + CK_OBJECT_HANDLE hKey /* handle of signing key */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_VerifyMessage) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_VOID_PTR pParameter, /* message specific parameter */ + CK_ULONG ulParameterLen, /* length of message specific parameter */ + CK_BYTE_PTR pData, /* data to sign */ + CK_ULONG ulDataLen, /* data to sign length */ + CK_BYTE_PTR pSignature, /* signature */ + CK_ULONG ulSignatureLen /* signature length */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_VerifyMessageBegin) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_VOID_PTR pParameter, /* message specific parameter */ + CK_ULONG ulParameterLen /* length of message specific parameter */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_VerifyMessageNext) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_VOID_PTR pParameter, /* message specific parameter */ + CK_ULONG ulParameterLen, /* length of message specific parameter */ + CK_BYTE_PTR pData, /* data to sign */ + CK_ULONG ulDataLen, /* data to sign length */ + CK_BYTE_PTR pSignature, /* signature */ + CK_ULONG ulSignatureLen /* signature length */ +); +#endif + +CK_PKCS11_FUNCTION_INFO(C_MessageVerifyFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + +#endif /* CK_PKCS11_2_0_ONLY */ + diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11t.h b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11t.h index d0531cc1c7f..ab6ef326e8b 100644 --- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11t.h +++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11t.h @@ -1,4 +1,4 @@ -/* Copyright (c) OASIS Open 2016. All Rights Reserved./ +/* Copyright (c) OASIS Open 2016, 2019. All Rights Reserved./ * /Distributed under the terms of the OASIS IPR Policy, * [http://www.oasis-open.org/policies-guidelines/ipr], AS-IS, WITHOUT ANY * IMPLIED OR EXPRESS WARRANTY; there is no warranty of MERCHANTABILITY, FITNESS FOR A @@ -17,8 +17,8 @@ #ifndef _PKCS11T_H_ #define _PKCS11T_H_ 1 -#define CRYPTOKI_VERSION_MAJOR 2 -#define CRYPTOKI_VERSION_MINOR 40 +#define CRYPTOKI_VERSION_MAJOR 3 +#define CRYPTOKI_VERSION_MINOR 0 #define CRYPTOKI_VERSION_AMENDMENT 0 #define CK_TRUE 1 @@ -77,19 +77,19 @@ typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR; typedef struct CK_VERSION { - CK_BYTE major; /* integer portion of version number */ - CK_BYTE minor; /* 1/100ths portion of version number */ + CK_BYTE major; /* integer portion of version number */ + CK_BYTE minor; /* 1/100ths portion of version number */ } CK_VERSION; typedef CK_VERSION CK_PTR CK_VERSION_PTR; typedef struct CK_INFO { - CK_VERSION cryptokiVersion; /* Cryptoki interface ver */ - CK_UTF8CHAR manufacturerID[32]; /* blank padded */ - CK_FLAGS flags; /* must be zero */ - CK_UTF8CHAR libraryDescription[32]; /* blank padded */ - CK_VERSION libraryVersion; /* version of library */ + CK_VERSION cryptokiVersion; /* Cryptoki interface ver */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ + CK_FLAGS flags; /* must be zero */ + CK_UTF8CHAR libraryDescription[32]; /* blank padded */ + CK_VERSION libraryVersion; /* version of library */ } CK_INFO; typedef CK_INFO CK_PTR CK_INFO_PTR; @@ -109,12 +109,12 @@ typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR; /* CK_SLOT_INFO provides information about a slot */ typedef struct CK_SLOT_INFO { - CK_UTF8CHAR slotDescription[64]; /* blank padded */ - CK_UTF8CHAR manufacturerID[32]; /* blank padded */ - CK_FLAGS flags; + CK_UTF8CHAR slotDescription[64]; /* blank padded */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ + CK_FLAGS flags; - CK_VERSION hardwareVersion; /* version of hardware */ - CK_VERSION firmwareVersion; /* version of firmware */ + CK_VERSION hardwareVersion; /* version of hardware */ + CK_VERSION firmwareVersion; /* version of firmware */ } CK_SLOT_INFO; /* flags: bit flags that provide capabilities of the slot @@ -129,25 +129,25 @@ typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR; /* CK_TOKEN_INFO provides information about a token */ typedef struct CK_TOKEN_INFO { - CK_UTF8CHAR label[32]; /* blank padded */ - CK_UTF8CHAR manufacturerID[32]; /* blank padded */ - CK_UTF8CHAR model[16]; /* blank padded */ - CK_CHAR serialNumber[16]; /* blank padded */ - CK_FLAGS flags; /* see below */ - - CK_ULONG ulMaxSessionCount; /* max open sessions */ - CK_ULONG ulSessionCount; /* sess. now open */ - CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */ - CK_ULONG ulRwSessionCount; /* R/W sess. now open */ - CK_ULONG ulMaxPinLen; /* in bytes */ - CK_ULONG ulMinPinLen; /* in bytes */ - CK_ULONG ulTotalPublicMemory; /* in bytes */ - CK_ULONG ulFreePublicMemory; /* in bytes */ - CK_ULONG ulTotalPrivateMemory; /* in bytes */ - CK_ULONG ulFreePrivateMemory; /* in bytes */ - CK_VERSION hardwareVersion; /* version of hardware */ - CK_VERSION firmwareVersion; /* version of firmware */ - CK_CHAR utcTime[16]; /* time */ + CK_UTF8CHAR label[32]; /* blank padded */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ + CK_UTF8CHAR model[16]; /* blank padded */ + CK_CHAR serialNumber[16]; /* blank padded */ + CK_FLAGS flags; /* see below */ + + CK_ULONG ulMaxSessionCount; /* max open sessions */ + CK_ULONG ulSessionCount; /* sess. now open */ + CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */ + CK_ULONG ulRwSessionCount; /* R/W sess. now open */ + CK_ULONG ulMaxPinLen; /* in bytes */ + CK_ULONG ulMinPinLen; /* in bytes */ + CK_ULONG ulTotalPublicMemory; /* in bytes */ + CK_ULONG ulFreePublicMemory; /* in bytes */ + CK_ULONG ulTotalPrivateMemory; /* in bytes */ + CK_ULONG ulFreePrivateMemory; /* in bytes */ + CK_VERSION hardwareVersion; /* version of hardware */ + CK_VERSION firmwareVersion; /* version of firmware */ + CK_CHAR utcTime[16]; /* time */ } CK_TOKEN_INFO; /* The flags parameter is defined as follows: @@ -278,10 +278,10 @@ typedef CK_ULONG CK_STATE; /* CK_SESSION_INFO provides information about a session */ typedef struct CK_SESSION_INFO { - CK_SLOT_ID slotID; - CK_STATE state; - CK_FLAGS flags; /* see below */ - CK_ULONG ulDeviceError; /* device-dependent error code */ + CK_SLOT_ID slotID; + CK_STATE state; + CK_FLAGS flags; /* see below */ + CK_ULONG ulDeviceError; /* device-dependent error code */ } CK_SESSION_INFO; /* The flags are defined in the following table: @@ -317,11 +317,20 @@ typedef CK_ULONG CK_OBJECT_CLASS; #define CKO_DOMAIN_PARAMETERS 0x00000006UL #define CKO_MECHANISM 0x00000007UL #define CKO_OTP_KEY 0x00000008UL +#define CKO_PROFILE 0x00000009UL #define CKO_VENDOR_DEFINED 0x80000000UL typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR; +/* Profile ID's */ +#define CKP_INVALID_ID 0x00000000UL +#define CKP_BASELINE_PROVIDER 0x00000001UL +#define CKP_EXTENDED_PROVIDER 0x00000002UL +#define CKP_AUTHENTICATION_TOKEN 0x00000003UL +#define CKP_PUBLIC_CERTIFICATES_TOKEN 0x00000004UL +#define CKP_VENDOR_DEFINED 0x80000000UL + /* CK_HW_FEATURE_TYPE is a value that identifies the hardware feature type * of an object with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */ @@ -369,6 +378,8 @@ typedef CK_ULONG CK_KEY_TYPE; #define CKK_CAMELLIA 0x00000025UL #define CKK_ARIA 0x00000026UL +/* the following definitions were added in the 2.30 header file, + * but never defined in the spec. */ #define CKK_MD5_HMAC 0x00000027UL #define CKK_SHA_1_HMAC 0x00000028UL #define CKK_RIPEMD128_HMAC 0x00000029UL @@ -382,8 +393,25 @@ typedef CK_ULONG CK_KEY_TYPE; #define CKK_GOSTR3410 0x00000030UL #define CKK_GOSTR3411 0x00000031UL #define CKK_GOST28147 0x00000032UL - - +#define CKK_CHACHA20 0x00000033UL +#define CKK_POLY1305 0x00000034UL +#define CKK_AES_XTS 0x00000035UL +#define CKK_SHA3_224_HMAC 0x00000036UL +#define CKK_SHA3_256_HMAC 0x00000037UL +#define CKK_SHA3_384_HMAC 0x00000038UL +#define CKK_SHA3_512_HMAC 0x00000039UL +#define CKK_BLAKE2B_160_HMAC 0x0000003aUL +#define CKK_BLAKE2B_256_HMAC 0x0000003bUL +#define CKK_BLAKE2B_384_HMAC 0x0000003cUL +#define CKK_BLAKE2B_512_HMAC 0x0000003dUL +#define CKK_SALSA20 0x0000003eUL +#define CKK_X2RATCHET 0x0000003fUL +#define CKK_EC_EDWARDS 0x00000040UL +#define CKK_EC_MONTGOMERY 0x00000041UL +#define CKK_HKDF 0x00000042UL +#define CKK_SHA512_224_HMAC 0x00000043UL +#define CKK_SHA512_256_HMAC 0x00000044UL +#define CKK_SHA512_T_HMAC 0x00000045UL #define CKK_VENDOR_DEFINED 0x80000000UL @@ -439,6 +467,7 @@ typedef CK_ULONG CK_ATTRIBUTE_TYPE; #define CKA_TOKEN 0x00000001UL #define CKA_PRIVATE 0x00000002UL #define CKA_LABEL 0x00000003UL +#define CKA_UNIQUE_ID 0x00000004UL #define CKA_APPLICATION 0x00000010UL #define CKA_VALUE 0x00000011UL #define CKA_OBJECT_ID 0x00000012UL @@ -556,6 +585,24 @@ typedef CK_ULONG CK_ATTRIBUTE_TYPE; #define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502UL #define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503UL #define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600UL) +#define CKA_PROFILE_ID 0x00000601UL +#define CKA_X2RATCHET_BAG 0x00000602UL +#define CKA_X2RATCHET_BAGSIZE 0x00000603UL +#define CKA_X2RATCHET_BOBS1STMSG 0x00000604UL +#define CKA_X2RATCHET_CKR 0x00000605UL +#define CKA_X2RATCHET_CKS 0x00000606UL +#define CKA_X2RATCHET_DHP 0x00000607UL +#define CKA_X2RATCHET_DHR 0x00000608UL +#define CKA_X2RATCHET_DHS 0x00000609UL +#define CKA_X2RATCHET_HKR 0x0000060aUL +#define CKA_X2RATCHET_HKS 0x0000060bUL +#define CKA_X2RATCHET_ISALICE 0x0000060cUL +#define CKA_X2RATCHET_NHKR 0x0000060dUL +#define CKA_X2RATCHET_NHKS 0x0000060eUL +#define CKA_X2RATCHET_NR 0x0000060fUL +#define CKA_X2RATCHET_NS 0x00000610UL +#define CKA_X2RATCHET_PNS 0x00000611UL +#define CKA_X2RATCHET_RK 0x00000612UL #define CKA_VENDOR_DEFINED 0x80000000UL @@ -563,18 +610,18 @@ typedef CK_ULONG CK_ATTRIBUTE_TYPE; * and value of an attribute */ typedef struct CK_ATTRIBUTE { - CK_ATTRIBUTE_TYPE type; - CK_VOID_PTR pValue; - CK_ULONG ulValueLen; /* in bytes */ + CK_ATTRIBUTE_TYPE type; + CK_VOID_PTR pValue; + CK_ULONG ulValueLen; /* in bytes */ } CK_ATTRIBUTE; typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR; /* CK_DATE is a structure that defines a date */ typedef struct CK_DATE{ - CK_CHAR year[4]; /* the year ("1900" - "9999") */ - CK_CHAR month[2]; /* the month ("01" - "12") */ - CK_CHAR day[2]; /* the day ("01" - "31") */ + CK_CHAR year[4]; /* the year ("1900" - "9999") */ + CK_CHAR month[2]; /* the month ("01" - "12") */ + CK_CHAR day[2]; /* the day ("01" - "31") */ } CK_DATE; @@ -610,6 +657,10 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_DSA_SHA256 0x00000014UL #define CKM_DSA_SHA384 0x00000015UL #define CKM_DSA_SHA512 0x00000016UL +#define CKM_DSA_SHA3_224 0x00000018UL +#define CKM_DSA_SHA3_256 0x00000019UL +#define CKM_DSA_SHA3_384 0x0000001AUL +#define CKM_DSA_SHA3_512 0x0000001BUL #define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020UL #define CKM_DH_PKCS_DERIVE 0x00000021UL @@ -643,6 +694,15 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_SHA512_T_HMAC_GENERAL 0x00000052UL #define CKM_SHA512_T_KEY_DERIVATION 0x00000053UL +#define CKM_SHA3_256_RSA_PKCS 0x00000060UL +#define CKM_SHA3_384_RSA_PKCS 0x00000061UL +#define CKM_SHA3_512_RSA_PKCS 0x00000062UL +#define CKM_SHA3_256_RSA_PKCS_PSS 0x00000063UL +#define CKM_SHA3_384_RSA_PKCS_PSS 0x00000064UL +#define CKM_SHA3_512_RSA_PKCS_PSS 0x00000065UL +#define CKM_SHA3_224_RSA_PKCS 0x00000066UL +#define CKM_SHA3_224_RSA_PKCS_PSS 0x00000067UL + #define CKM_RC2_KEY_GEN 0x00000100UL #define CKM_RC2_ECB 0x00000101UL #define CKM_RC2_CBC 0x00000102UL @@ -724,6 +784,24 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_ACTI 0x000002A0UL #define CKM_ACTI_KEY_GEN 0x000002A1UL +#define CKM_SHA3_256 0x000002B0UL +#define CKM_SHA3_256_HMAC 0x000002B1UL +#define CKM_SHA3_256_HMAC_GENERAL 0x000002B2UL +#define CKM_SHA3_256_KEY_GEN 0x000002B3UL +#define CKM_SHA3_224 0x000002B5UL +#define CKM_SHA3_224_HMAC 0x000002B6UL +#define CKM_SHA3_224_HMAC_GENERAL 0x000002B7UL +#define CKM_SHA3_224_KEY_GEN 0x000002B8UL +#define CKM_SHA3_384 0x000002C0UL +#define CKM_SHA3_384_HMAC 0x000002C1UL +#define CKM_SHA3_384_HMAC_GENERAL 0x000002C2UL +#define CKM_SHA3_384_KEY_GEN 0x000002C3UL +#define CKM_SHA3_512 0x000002D0UL +#define CKM_SHA3_512_HMAC 0x000002D1UL +#define CKM_SHA3_512_HMAC_GENERAL 0x000002D2UL +#define CKM_SHA3_512_KEY_GEN 0x000002D3UL + + #define CKM_CAST_KEY_GEN 0x00000300UL #define CKM_CAST_ECB 0x00000301UL #define CKM_CAST_CBC 0x00000302UL @@ -789,6 +867,18 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_SHA384_KEY_DERIVATION 0x00000394UL #define CKM_SHA512_KEY_DERIVATION 0x00000395UL #define CKM_SHA224_KEY_DERIVATION 0x00000396UL +#define CKM_SHA3_256_KEY_DERIVATION 0x00000397UL +#define CKM_SHA3_224_KEY_DERIVATION 0x00000398UL +#define CKM_SHA3_384_KEY_DERIVATION 0x00000399UL +#define CKM_SHA3_512_KEY_DERIVATION 0x0000039AUL +#define CKM_SHAKE_128_KEY_DERIVATION 0x0000039BUL +#define CKM_SHAKE_256_KEY_DERIVATION 0x0000039CUL +#define CKM_SHA3_256_KEY_DERIVE CKM_SHA3_256_KEY_DERIVATION +#define CKM_SHA3_224_KEY_DERIVE CKM_SHA3_224_KEY_DERIVATION +#define CKM_SHA3_384_KEY_DERIVE CKM_SHA3_384_KEY_DERIVATION +#define CKM_SHA3_512_KEY_DERIVE CKM_SHA3_512_KEY_DERIVATION +#define CKM_SHAKE_128_KEY_DERIVE CKM_SHAKE_128_KEY_DERIVATION +#define CKM_SHAKE_256_KEY_DERIVE CKM_SHAKE_256_KEY_DERIVATION #define CKM_PBE_MD2_DES_CBC 0x000003A0UL #define CKM_PBE_MD5_DES_CBC 0x000003A1UL @@ -816,8 +906,6 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE 0x000003D4UL #define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE 0x000003D5UL -#define CKM_TLS10_MAC_SERVER 0x000003D6UL -#define CKM_TLS10_MAC_CLIENT 0x000003D7UL #define CKM_TLS12_MAC 0x000003D8UL #define CKM_TLS12_KDF 0x000003D9UL #define CKM_TLS12_MASTER_KEY_DERIVE 0x000003E0UL @@ -895,6 +983,7 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_ECDSA_SHA256 0x00001044UL #define CKM_ECDSA_SHA384 0x00001045UL #define CKM_ECDSA_SHA512 0x00001046UL +#define CKM_EC_KEY_PAIR_GEN_W_EXTRA_BITS 0x0000140BUL #define CKM_ECDH1_DERIVE 0x00001050UL #define CKM_ECDH1_COFACTOR_DERIVE 0x00001051UL @@ -911,6 +1000,8 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_JUNIPER_WRAP 0x00001065UL #define CKM_FASTHASH 0x00001070UL +#define CKM_AES_XTS 0x00001071UL +#define CKM_AES_XTS_KEY_GEN 0x00001072UL #define CKM_AES_KEY_GEN 0x00001080UL #define CKM_AES_ECB 0x00001081UL #define CKM_AES_CBC 0x00001082UL @@ -954,12 +1045,17 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_GOST28147 0x00001222UL #define CKM_GOST28147_MAC 0x00001223UL #define CKM_GOST28147_KEY_WRAP 0x00001224UL - +#define CKM_CHACHA20_KEY_GEN 0x00001225UL +#define CKM_CHACHA20 0x00001226UL +#define CKM_POLY1305_KEY_GEN 0x00001227UL +#define CKM_POLY1305 0x00001228UL #define CKM_DSA_PARAMETER_GEN 0x00002000UL #define CKM_DH_PKCS_PARAMETER_GEN 0x00002001UL #define CKM_X9_42_DH_PARAMETER_GEN 0x00002002UL -#define CKM_DSA_PROBABLISTIC_PARAMETER_GEN 0x00002003UL +#define CKM_DSA_PROBABILISTIC_PARAMETER_GEN 0x00002003UL +#define CKM_DSA_PROBABLISTIC_PARAMETER_GEN CKM_DSA_PROBABILISTIC_PARAMETER_GEN #define CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN 0x00002004UL +#define CKM_DSA_FIPS_G_GEN 0x00002005UL #define CKM_AES_OFB 0x00002104UL #define CKM_AES_CFB64 0x00002105UL @@ -969,10 +1065,66 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_AES_CFB1 0x00002108UL #define CKM_AES_KEY_WRAP 0x00002109UL /* WAS: 0x00001090 */ #define CKM_AES_KEY_WRAP_PAD 0x0000210AUL /* WAS: 0x00001091 */ +#define CKM_AES_KEY_WRAP_KWP 0x0000210BUL #define CKM_RSA_PKCS_TPM_1_1 0x00004001UL #define CKM_RSA_PKCS_OAEP_TPM_1_1 0x00004002UL +#define CKM_SHA_1_KEY_GEN 0x00004003UL +#define CKM_SHA224_KEY_GEN 0x00004004UL +#define CKM_SHA256_KEY_GEN 0x00004005UL +#define CKM_SHA384_KEY_GEN 0x00004006UL +#define CKM_SHA512_KEY_GEN 0x00004007UL +#define CKM_SHA512_224_KEY_GEN 0x00004008UL +#define CKM_SHA512_256_KEY_GEN 0x00004009UL +#define CKM_SHA512_T_KEY_GEN 0x0000400aUL +#define CKM_NULL 0x0000400bUL +#define CKM_BLAKE2B_160 0x0000400cUL +#define CKM_BLAKE2B_160_HMAC 0x0000400dUL +#define CKM_BLAKE2B_160_HMAC_GENERAL 0x0000400eUL +#define CKM_BLAKE2B_160_KEY_DERIVE 0x0000400fUL +#define CKM_BLAKE2B_160_KEY_GEN 0x00004010UL +#define CKM_BLAKE2B_256 0x00004011UL +#define CKM_BLAKE2B_256_HMAC 0x00004012UL +#define CKM_BLAKE2B_256_HMAC_GENERAL 0x00004013UL +#define CKM_BLAKE2B_256_KEY_DERIVE 0x00004014UL +#define CKM_BLAKE2B_256_KEY_GEN 0x00004015UL +#define CKM_BLAKE2B_384 0x00004016UL +#define CKM_BLAKE2B_384_HMAC 0x00004017UL +#define CKM_BLAKE2B_384_HMAC_GENERAL 0x00004018UL +#define CKM_BLAKE2B_384_KEY_DERIVE 0x00004019UL +#define CKM_BLAKE2B_384_KEY_GEN 0x0000401aUL +#define CKM_BLAKE2B_512 0x0000401bUL +#define CKM_BLAKE2B_512_HMAC 0x0000401cUL +#define CKM_BLAKE2B_512_HMAC_GENERAL 0x0000401dUL +#define CKM_BLAKE2B_512_KEY_DERIVE 0x0000401eUL +#define CKM_BLAKE2B_512_KEY_GEN 0x0000401fUL +#define CKM_SALSA20 0x00004020UL +#define CKM_CHACHA20_POLY1305 0x00004021UL +#define CKM_SALSA20_POLY1305 0x00004022UL +#define CKM_X3DH_INITIALIZE 0x00004023UL +#define CKM_X3DH_RESPOND 0x00004024UL +#define CKM_X2RATCHET_INITIALIZE 0x00004025UL +#define CKM_X2RATCHET_RESPOND 0x00004026UL +#define CKM_X2RATCHET_ENCRYPT 0x00004027UL +#define CKM_X2RATCHET_DECRYPT 0x00004028UL +#define CKM_XEDDSA 0x00004029UL +#define CKM_HKDF_DERIVE 0x0000402aUL +#define CKM_HKDF_DATA 0x0000402bUL +#define CKM_HKDF_KEY_GEN 0x0000402cUL +#define CKM_SALSA20_KEY_GEN 0x0000402dUL + +#define CKM_ECDSA_SHA3_224 0x00001047UL +#define CKM_ECDSA_SHA3_256 0x00001048UL +#define CKM_ECDSA_SHA3_384 0x00001049UL +#define CKM_ECDSA_SHA3_512 0x0000104aUL +#define CKM_EC_EDWARDS_KEY_PAIR_GEN 0x00001055UL +#define CKM_EC_MONTGOMERY_KEY_PAIR_GEN 0x00001056UL +#define CKM_EDDSA 0x00001057UL +#define CKM_SP800_108_COUNTER_KDF 0x000003acUL +#define CKM_SP800_108_FEEDBACK_KDF 0x000003adUL +#define CKM_SP800_108_DOUBLE_PIPELINE_KDF 0x000003aeUL + #define CKM_VENDOR_DEFINED 0x80000000UL typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR; @@ -982,9 +1134,9 @@ typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR; * mechanism */ typedef struct CK_MECHANISM { - CK_MECHANISM_TYPE mechanism; - CK_VOID_PTR pParameter; - CK_ULONG ulParameterLen; /* in bytes */ + CK_MECHANISM_TYPE mechanism; + CK_VOID_PTR pParameter; + CK_ULONG ulParameterLen; /* in bytes */ } CK_MECHANISM; typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR; @@ -994,9 +1146,9 @@ typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR; * mechanism */ typedef struct CK_MECHANISM_INFO { - CK_ULONG ulMinKeySize; - CK_ULONG ulMaxKeySize; - CK_FLAGS flags; + CK_ULONG ulMinKeySize; + CK_ULONG ulMaxKeySize; + CK_FLAGS flags; } CK_MECHANISM_INFO; /* The flags are defined as follows: @@ -1004,6 +1156,14 @@ typedef struct CK_MECHANISM_INFO { #define CKF_HW 0x00000001UL /* performed by HW */ /* Specify whether or not a mechanism can be used for a particular task */ +#define CKF_MESSAGE_ENCRYPT 0x00000002UL +#define CKF_MESSAGE_DECRYPT 0x00000004UL +#define CKF_MESSAGE_SIGN 0x00000008UL +#define CKF_MESSAGE_VERIFY 0x00000010UL +#define CKF_MULTI_MESSAGE 0x00000020UL +#define CKF_MULTI_MESSGE CKF_MULTI_MESSAGE +#define CKF_FIND_OBJECTS 0x00000040UL + #define CKF_ENCRYPT 0x00000100UL #define CKF_DECRYPT 0x00000200UL #define CKF_DIGEST 0x00000400UL @@ -1023,9 +1183,11 @@ typedef struct CK_MECHANISM_INFO { #define CKF_EC_F_P 0x00100000UL #define CKF_EC_F_2M 0x00200000UL #define CKF_EC_ECPARAMETERS 0x00400000UL -#define CKF_EC_NAMEDCURVE 0x00800000UL +#define CKF_EC_OID 0x00800000UL +#define CKF_EC_NAMEDCURVE CKF_EC_OID /* deprecated since PKCS#11 3.00 */ #define CKF_EC_UNCOMPRESS 0x01000000UL #define CKF_EC_COMPRESS 0x02000000UL +#define CKF_EC_CURVENAME 0x04000000UL #define CKF_EXTENSION 0x80000000UL @@ -1063,6 +1225,7 @@ typedef CK_ULONG CK_RV; #define CKR_DEVICE_REMOVED 0x00000032UL #define CKR_ENCRYPTED_DATA_INVALID 0x00000040UL #define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041UL +#define CKR_AEAD_DECRYPT_FAILED 0x00000042UL #define CKR_FUNCTION_CANCELED 0x00000050UL #define CKR_FUNCTION_NOT_PARALLEL 0x00000051UL @@ -1155,15 +1318,17 @@ typedef CK_ULONG CK_RV; #define CKR_PUBLIC_KEY_INVALID 0x000001B9UL #define CKR_FUNCTION_REJECTED 0x00000200UL +#define CKR_TOKEN_RESOURCE_EXCEEDED 0x00000201UL +#define CKR_OPERATION_CANCEL_FAILED 0x00000202UL #define CKR_VENDOR_DEFINED 0x80000000UL /* CK_NOTIFY is an application callback that processes events */ typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)( - CK_SESSION_HANDLE hSession, /* the session's handle */ - CK_NOTIFICATION event, - CK_VOID_PTR pApplication /* passed to C_OpenSession */ + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_NOTIFICATION event, + CK_VOID_PTR pApplication /* passed to C_OpenSession */ ); @@ -1172,17 +1337,31 @@ typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)( * Cryptoki functions */ typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST; +typedef struct CK_FUNCTION_LIST_3_0 CK_FUNCTION_LIST_3_0; typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR; +typedef CK_FUNCTION_LIST_3_0 CK_PTR CK_FUNCTION_LIST_3_0_PTR; typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR; +typedef CK_FUNCTION_LIST_3_0_PTR CK_PTR CK_FUNCTION_LIST_3_0_PTR_PTR; + +typedef struct CK_INTERFACE { + CK_CHAR *pInterfaceName; + CK_VOID_PTR pFunctionList; + CK_FLAGS flags; +} CK_INTERFACE; + +typedef CK_INTERFACE CK_PTR CK_INTERFACE_PTR; +typedef CK_INTERFACE_PTR CK_PTR CK_INTERFACE_PTR_PTR; + +#define CKF_END_OF_MESSAGE 0x00000001UL /* CK_CREATEMUTEX is an application callback for creating a * mutex object */ typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)( - CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */ + CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */ ); @@ -1190,13 +1369,13 @@ typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)( * mutex object */ typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)( - CK_VOID_PTR pMutex /* pointer to mutex */ + CK_VOID_PTR pMutex /* pointer to mutex */ ); /* CK_LOCKMUTEX is an application callback for locking a mutex */ typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)( - CK_VOID_PTR pMutex /* pointer to mutex */ + CK_VOID_PTR pMutex /* pointer to mutex */ ); @@ -1204,20 +1383,22 @@ typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)( * mutex */ typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)( - CK_VOID_PTR pMutex /* pointer to mutex */ + CK_VOID_PTR pMutex /* pointer to mutex */ ); +/* Get functionlist flags */ +#define CKF_INTERFACE_FORK_SAFE 0x00000001UL /* CK_C_INITIALIZE_ARGS provides the optional arguments to * C_Initialize */ typedef struct CK_C_INITIALIZE_ARGS { - CK_CREATEMUTEX CreateMutex; - CK_DESTROYMUTEX DestroyMutex; - CK_LOCKMUTEX LockMutex; - CK_UNLOCKMUTEX UnlockMutex; - CK_FLAGS flags; - CK_VOID_PTR pReserved; + CK_CREATEMUTEX CreateMutex; + CK_DESTROYMUTEX DestroyMutex; + CK_LOCKMUTEX LockMutex; + CK_UNLOCKMUTEX UnlockMutex; + CK_FLAGS flags; + CK_VOID_PTR pReserved; } CK_C_INITIALIZE_ARGS; /* flags: bit flags that provide capabilities of the slot @@ -1229,6 +1410,7 @@ typedef struct CK_C_INITIALIZE_ARGS { typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR; + /* additional flags for parameters to functions */ /* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */ @@ -1249,6 +1431,10 @@ typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR; #define CKG_MGF1_SHA384 0x00000003UL #define CKG_MGF1_SHA512 0x00000004UL #define CKG_MGF1_SHA224 0x00000005UL +#define CKG_MGF1_SHA3_224 0x00000006UL +#define CKG_MGF1_SHA3_256 0x00000007UL +#define CKG_MGF1_SHA3_384 0x00000008UL +#define CKG_MGF1_SHA3_512 0x00000009UL /* CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source * of the encoding parameter when formatting a message block @@ -1265,11 +1451,11 @@ typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR; * CKM_RSA_PKCS_OAEP mechanism. */ typedef struct CK_RSA_PKCS_OAEP_PARAMS { - CK_MECHANISM_TYPE hashAlg; - CK_RSA_PKCS_MGF_TYPE mgf; - CK_RSA_PKCS_OAEP_SOURCE_TYPE source; - CK_VOID_PTR pSourceData; - CK_ULONG ulSourceDataLen; + CK_MECHANISM_TYPE hashAlg; + CK_RSA_PKCS_MGF_TYPE mgf; + CK_RSA_PKCS_OAEP_SOURCE_TYPE source; + CK_VOID_PTR pSourceData; + CK_ULONG ulSourceDataLen; } CK_RSA_PKCS_OAEP_PARAMS; typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR; @@ -1278,14 +1464,15 @@ typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR; * CKM_RSA_PKCS_PSS mechanism(s). */ typedef struct CK_RSA_PKCS_PSS_PARAMS { - CK_MECHANISM_TYPE hashAlg; - CK_RSA_PKCS_MGF_TYPE mgf; - CK_ULONG sLen; + CK_MECHANISM_TYPE hashAlg; + CK_RSA_PKCS_MGF_TYPE mgf; + CK_ULONG sLen; } CK_RSA_PKCS_PSS_PARAMS; typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR; typedef CK_ULONG CK_EC_KDF_TYPE; +typedef CK_EC_KDF_TYPE CK_PTR CK_EC_KDF_TYPE_PTR; /* The following EC Key Derivation Functions are defined */ #define CKD_NULL 0x00000001UL @@ -1299,18 +1486,34 @@ typedef CK_ULONG CK_EC_KDF_TYPE; #define CKD_SHA384_KDF 0x00000007UL #define CKD_SHA512_KDF 0x00000008UL #define CKD_CPDIVERSIFY_KDF 0x00000009UL - +#define CKD_SHA3_224_KDF 0x0000000AUL +#define CKD_SHA3_256_KDF 0x0000000BUL +#define CKD_SHA3_384_KDF 0x0000000CUL +#define CKD_SHA3_512_KDF 0x0000000DUL +#define CKD_SHA1_KDF_SP800 0x0000000EUL +#define CKD_SHA224_KDF_SP800 0x0000000FUL +#define CKD_SHA256_KDF_SP800 0x00000010UL +#define CKD_SHA384_KDF_SP800 0x00000011UL +#define CKD_SHA512_KDF_SP800 0x00000012UL +#define CKD_SHA3_224_KDF_SP800 0x00000013UL +#define CKD_SHA3_256_KDF_SP800 0x00000014UL +#define CKD_SHA3_384_KDF_SP800 0x00000015UL +#define CKD_SHA3_512_KDF_SP800 0x00000016UL +#define CKD_BLAKE2B_160_KDF 0x00000017UL +#define CKD_BLAKE2B_256_KDF 0x00000018UL +#define CKD_BLAKE2B_384_KDF 0x00000019UL +#define CKD_BLAKE2B_512_KDF 0x0000001aUL /* CK_ECDH1_DERIVE_PARAMS provides the parameters to the * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms, * where each party contributes one key pair. */ typedef struct CK_ECDH1_DERIVE_PARAMS { - CK_EC_KDF_TYPE kdf; - CK_ULONG ulSharedDataLen; - CK_BYTE_PTR pSharedData; - CK_ULONG ulPublicDataLen; - CK_BYTE_PTR pPublicData; + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; } CK_ECDH1_DERIVE_PARAMS; typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR; @@ -1320,30 +1523,30 @@ typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR; * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */ typedef struct CK_ECDH2_DERIVE_PARAMS { - CK_EC_KDF_TYPE kdf; - CK_ULONG ulSharedDataLen; - CK_BYTE_PTR pSharedData; - CK_ULONG ulPublicDataLen; - CK_BYTE_PTR pPublicData; - CK_ULONG ulPrivateDataLen; - CK_OBJECT_HANDLE hPrivateData; - CK_ULONG ulPublicDataLen2; - CK_BYTE_PTR pPublicData2; + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; } CK_ECDH2_DERIVE_PARAMS; typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR; typedef struct CK_ECMQV_DERIVE_PARAMS { - CK_EC_KDF_TYPE kdf; - CK_ULONG ulSharedDataLen; - CK_BYTE_PTR pSharedData; - CK_ULONG ulPublicDataLen; - CK_BYTE_PTR pPublicData; - CK_ULONG ulPrivateDataLen; - CK_OBJECT_HANDLE hPrivateData; - CK_ULONG ulPublicDataLen2; - CK_BYTE_PTR pPublicData2; - CK_OBJECT_HANDLE publicKey; + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; + CK_OBJECT_HANDLE publicKey; } CK_ECMQV_DERIVE_PARAMS; typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR; @@ -1359,11 +1562,11 @@ typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR; * contributes one key pair */ typedef struct CK_X9_42_DH1_DERIVE_PARAMS { - CK_X9_42_DH_KDF_TYPE kdf; - CK_ULONG ulOtherInfoLen; - CK_BYTE_PTR pOtherInfo; - CK_ULONG ulPublicDataLen; - CK_BYTE_PTR pPublicData; + CK_X9_42_DH_KDF_TYPE kdf; + CK_ULONG ulOtherInfoLen; + CK_BYTE_PTR pOtherInfo; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; } CK_X9_42_DH1_DERIVE_PARAMS; typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR; @@ -1373,30 +1576,30 @@ typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR; * mechanisms, where each party contributes two key pairs */ typedef struct CK_X9_42_DH2_DERIVE_PARAMS { - CK_X9_42_DH_KDF_TYPE kdf; - CK_ULONG ulOtherInfoLen; - CK_BYTE_PTR pOtherInfo; - CK_ULONG ulPublicDataLen; - CK_BYTE_PTR pPublicData; - CK_ULONG ulPrivateDataLen; - CK_OBJECT_HANDLE hPrivateData; - CK_ULONG ulPublicDataLen2; - CK_BYTE_PTR pPublicData2; + CK_X9_42_DH_KDF_TYPE kdf; + CK_ULONG ulOtherInfoLen; + CK_BYTE_PTR pOtherInfo; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; } CK_X9_42_DH2_DERIVE_PARAMS; typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR; typedef struct CK_X9_42_MQV_DERIVE_PARAMS { - CK_X9_42_DH_KDF_TYPE kdf; - CK_ULONG ulOtherInfoLen; - CK_BYTE_PTR pOtherInfo; - CK_ULONG ulPublicDataLen; - CK_BYTE_PTR pPublicData; - CK_ULONG ulPrivateDataLen; - CK_OBJECT_HANDLE hPrivateData; - CK_ULONG ulPublicDataLen2; - CK_BYTE_PTR pPublicData2; - CK_OBJECT_HANDLE publicKey; + CK_X9_42_DH_KDF_TYPE kdf; + CK_ULONG ulOtherInfoLen; + CK_BYTE_PTR pOtherInfo; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; + CK_OBJECT_HANDLE publicKey; } CK_X9_42_MQV_DERIVE_PARAMS; typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR; @@ -1405,12 +1608,12 @@ typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR; * CKM_KEA_DERIVE mechanism */ typedef struct CK_KEA_DERIVE_PARAMS { - CK_BBOOL isSender; - CK_ULONG ulRandomLen; - CK_BYTE_PTR pRandomA; - CK_BYTE_PTR pRandomB; - CK_ULONG ulPublicDataLen; - CK_BYTE_PTR pPublicData; + CK_BBOOL isSender; + CK_ULONG ulRandomLen; + CK_BYTE_PTR pRandomA; + CK_BYTE_PTR pRandomB; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; } CK_KEA_DERIVE_PARAMS; typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR; @@ -1429,8 +1632,8 @@ typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR; * mechanism */ typedef struct CK_RC2_CBC_PARAMS { - CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ - CK_BYTE iv[8]; /* IV for CBC mode */ + CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ + CK_BYTE iv[8]; /* IV for CBC mode */ } CK_RC2_CBC_PARAMS; typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR; @@ -1440,20 +1643,20 @@ typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR; * CKM_RC2_MAC_GENERAL mechanism */ typedef struct CK_RC2_MAC_GENERAL_PARAMS { - CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ - CK_ULONG ulMacLength; /* Length of MAC in bytes */ + CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ + CK_ULONG ulMacLength; /* Length of MAC in bytes */ } CK_RC2_MAC_GENERAL_PARAMS; typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \ - CK_RC2_MAC_GENERAL_PARAMS_PTR; + CK_RC2_MAC_GENERAL_PARAMS_PTR; /* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and * CKM_RC5_MAC mechanisms */ typedef struct CK_RC5_PARAMS { - CK_ULONG ulWordsize; /* wordsize in bits */ - CK_ULONG ulRounds; /* number of rounds */ + CK_ULONG ulWordsize; /* wordsize in bits */ + CK_ULONG ulRounds; /* number of rounds */ } CK_RC5_PARAMS; typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR; @@ -1463,10 +1666,10 @@ typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR; * mechanism */ typedef struct CK_RC5_CBC_PARAMS { - CK_ULONG ulWordsize; /* wordsize in bits */ - CK_ULONG ulRounds; /* number of rounds */ - CK_BYTE_PTR pIv; /* pointer to IV */ - CK_ULONG ulIvLen; /* length of IV in bytes */ + CK_ULONG ulWordsize; /* wordsize in bits */ + CK_ULONG ulRounds; /* number of rounds */ + CK_BYTE_PTR pIv; /* pointer to IV */ + CK_ULONG ulIvLen; /* length of IV in bytes */ } CK_RC5_CBC_PARAMS; typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR; @@ -1476,13 +1679,13 @@ typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR; * CKM_RC5_MAC_GENERAL mechanism */ typedef struct CK_RC5_MAC_GENERAL_PARAMS { - CK_ULONG ulWordsize; /* wordsize in bits */ - CK_ULONG ulRounds; /* number of rounds */ - CK_ULONG ulMacLength; /* Length of MAC in bytes */ + CK_ULONG ulWordsize; /* wordsize in bits */ + CK_ULONG ulRounds; /* number of rounds */ + CK_ULONG ulMacLength; /* Length of MAC in bytes */ } CK_RC5_MAC_GENERAL_PARAMS; typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \ - CK_RC5_MAC_GENERAL_PARAMS_PTR; + CK_RC5_MAC_GENERAL_PARAMS_PTR; /* CK_MAC_GENERAL_PARAMS provides the parameters to most block * ciphers' MAC_GENERAL mechanisms. Its value is the length of @@ -1493,73 +1696,75 @@ typedef CK_ULONG CK_MAC_GENERAL_PARAMS; typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR; typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS { - CK_BYTE iv[8]; - CK_BYTE_PTR pData; - CK_ULONG length; + CK_BYTE iv[8]; + CK_BYTE_PTR pData; + CK_ULONG length; } CK_DES_CBC_ENCRYPT_DATA_PARAMS; -typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR; +typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR \ + CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR; typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS { - CK_BYTE iv[16]; - CK_BYTE_PTR pData; - CK_ULONG length; + CK_BYTE iv[16]; + CK_BYTE_PTR pData; + CK_ULONG length; } CK_AES_CBC_ENCRYPT_DATA_PARAMS; -typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR; +typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR \ + CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR; /* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the * CKM_SKIPJACK_PRIVATE_WRAP mechanism */ typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS { - CK_ULONG ulPasswordLen; - CK_BYTE_PTR pPassword; - CK_ULONG ulPublicDataLen; - CK_BYTE_PTR pPublicData; - CK_ULONG ulPAndGLen; - CK_ULONG ulQLen; - CK_ULONG ulRandomLen; - CK_BYTE_PTR pRandomA; - CK_BYTE_PTR pPrimeP; - CK_BYTE_PTR pBaseG; - CK_BYTE_PTR pSubprimeQ; + CK_ULONG ulPasswordLen; + CK_BYTE_PTR pPassword; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPAndGLen; + CK_ULONG ulQLen; + CK_ULONG ulRandomLen; + CK_BYTE_PTR pRandomA; + CK_BYTE_PTR pPrimeP; + CK_BYTE_PTR pBaseG; + CK_BYTE_PTR pSubprimeQ; } CK_SKIPJACK_PRIVATE_WRAP_PARAMS; typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \ - CK_SKIPJACK_PRIVATE_WRAP_PARAMS_PTR; + CK_SKIPJACK_PRIVATE_WRAP_PARAMS_PTR; /* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the * CKM_SKIPJACK_RELAYX mechanism */ typedef struct CK_SKIPJACK_RELAYX_PARAMS { - CK_ULONG ulOldWrappedXLen; - CK_BYTE_PTR pOldWrappedX; - CK_ULONG ulOldPasswordLen; - CK_BYTE_PTR pOldPassword; - CK_ULONG ulOldPublicDataLen; - CK_BYTE_PTR pOldPublicData; - CK_ULONG ulOldRandomLen; - CK_BYTE_PTR pOldRandomA; - CK_ULONG ulNewPasswordLen; - CK_BYTE_PTR pNewPassword; - CK_ULONG ulNewPublicDataLen; - CK_BYTE_PTR pNewPublicData; - CK_ULONG ulNewRandomLen; - CK_BYTE_PTR pNewRandomA; + CK_ULONG ulOldWrappedXLen; + CK_BYTE_PTR pOldWrappedX; + CK_ULONG ulOldPasswordLen; + CK_BYTE_PTR pOldPassword; + CK_ULONG ulOldPublicDataLen; + CK_BYTE_PTR pOldPublicData; + CK_ULONG ulOldRandomLen; + CK_BYTE_PTR pOldRandomA; + CK_ULONG ulNewPasswordLen; + CK_BYTE_PTR pNewPassword; + CK_ULONG ulNewPublicDataLen; + CK_BYTE_PTR pNewPublicData; + CK_ULONG ulNewRandomLen; + CK_BYTE_PTR pNewRandomA; } CK_SKIPJACK_RELAYX_PARAMS; typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \ - CK_SKIPJACK_RELAYX_PARAMS_PTR; + CK_SKIPJACK_RELAYX_PARAMS_PTR; typedef struct CK_PBE_PARAMS { - CK_BYTE_PTR pInitVector; - CK_UTF8CHAR_PTR pPassword; - CK_ULONG ulPasswordLen; - CK_BYTE_PTR pSalt; - CK_ULONG ulSaltLen; - CK_ULONG ulIteration; + CK_BYTE_PTR pInitVector; + CK_UTF8CHAR_PTR pPassword; + CK_ULONG ulPasswordLen; + CK_BYTE_PTR pSalt; + CK_ULONG ulSaltLen; + CK_ULONG ulIteration; } CK_PBE_PARAMS; typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR; @@ -1569,134 +1774,134 @@ typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR; * CKM_KEY_WRAP_SET_OAEP mechanism */ typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS { - CK_BYTE bBC; /* block contents byte */ - CK_BYTE_PTR pX; /* extra data */ - CK_ULONG ulXLen; /* length of extra data in bytes */ + CK_BYTE bBC; /* block contents byte */ + CK_BYTE_PTR pX; /* extra data */ + CK_ULONG ulXLen; /* length of extra data in bytes */ } CK_KEY_WRAP_SET_OAEP_PARAMS; typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR CK_KEY_WRAP_SET_OAEP_PARAMS_PTR; typedef struct CK_SSL3_RANDOM_DATA { - CK_BYTE_PTR pClientRandom; - CK_ULONG ulClientRandomLen; - CK_BYTE_PTR pServerRandom; - CK_ULONG ulServerRandomLen; + CK_BYTE_PTR pClientRandom; + CK_ULONG ulClientRandomLen; + CK_BYTE_PTR pServerRandom; + CK_ULONG ulServerRandomLen; } CK_SSL3_RANDOM_DATA; typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS { - CK_SSL3_RANDOM_DATA RandomInfo; - CK_VERSION_PTR pVersion; + CK_SSL3_RANDOM_DATA RandomInfo; + CK_VERSION_PTR pVersion; } CK_SSL3_MASTER_KEY_DERIVE_PARAMS; typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \ - CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR; + CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR; typedef struct CK_SSL3_KEY_MAT_OUT { - CK_OBJECT_HANDLE hClientMacSecret; - CK_OBJECT_HANDLE hServerMacSecret; - CK_OBJECT_HANDLE hClientKey; - CK_OBJECT_HANDLE hServerKey; - CK_BYTE_PTR pIVClient; - CK_BYTE_PTR pIVServer; + CK_OBJECT_HANDLE hClientMacSecret; + CK_OBJECT_HANDLE hServerMacSecret; + CK_OBJECT_HANDLE hClientKey; + CK_OBJECT_HANDLE hServerKey; + CK_BYTE_PTR pIVClient; + CK_BYTE_PTR pIVServer; } CK_SSL3_KEY_MAT_OUT; typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR; typedef struct CK_SSL3_KEY_MAT_PARAMS { - CK_ULONG ulMacSizeInBits; - CK_ULONG ulKeySizeInBits; - CK_ULONG ulIVSizeInBits; - CK_BBOOL bIsExport; - CK_SSL3_RANDOM_DATA RandomInfo; - CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial; + CK_ULONG ulMacSizeInBits; + CK_ULONG ulKeySizeInBits; + CK_ULONG ulIVSizeInBits; + CK_BBOOL bIsExport; + CK_SSL3_RANDOM_DATA RandomInfo; + CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial; } CK_SSL3_KEY_MAT_PARAMS; typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR; typedef struct CK_TLS_PRF_PARAMS { - CK_BYTE_PTR pSeed; - CK_ULONG ulSeedLen; - CK_BYTE_PTR pLabel; - CK_ULONG ulLabelLen; - CK_BYTE_PTR pOutput; - CK_ULONG_PTR pulOutputLen; + CK_BYTE_PTR pSeed; + CK_ULONG ulSeedLen; + CK_BYTE_PTR pLabel; + CK_ULONG ulLabelLen; + CK_BYTE_PTR pOutput; + CK_ULONG_PTR pulOutputLen; } CK_TLS_PRF_PARAMS; typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR; typedef struct CK_WTLS_RANDOM_DATA { - CK_BYTE_PTR pClientRandom; - CK_ULONG ulClientRandomLen; - CK_BYTE_PTR pServerRandom; - CK_ULONG ulServerRandomLen; + CK_BYTE_PTR pClientRandom; + CK_ULONG ulClientRandomLen; + CK_BYTE_PTR pServerRandom; + CK_ULONG ulServerRandomLen; } CK_WTLS_RANDOM_DATA; typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR; typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS { - CK_MECHANISM_TYPE DigestMechanism; - CK_WTLS_RANDOM_DATA RandomInfo; - CK_BYTE_PTR pVersion; + CK_MECHANISM_TYPE DigestMechanism; + CK_WTLS_RANDOM_DATA RandomInfo; + CK_BYTE_PTR pVersion; } CK_WTLS_MASTER_KEY_DERIVE_PARAMS; typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \ - CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR; + CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR; typedef struct CK_WTLS_PRF_PARAMS { - CK_MECHANISM_TYPE DigestMechanism; - CK_BYTE_PTR pSeed; - CK_ULONG ulSeedLen; - CK_BYTE_PTR pLabel; - CK_ULONG ulLabelLen; - CK_BYTE_PTR pOutput; - CK_ULONG_PTR pulOutputLen; + CK_MECHANISM_TYPE DigestMechanism; + CK_BYTE_PTR pSeed; + CK_ULONG ulSeedLen; + CK_BYTE_PTR pLabel; + CK_ULONG ulLabelLen; + CK_BYTE_PTR pOutput; + CK_ULONG_PTR pulOutputLen; } CK_WTLS_PRF_PARAMS; typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR; typedef struct CK_WTLS_KEY_MAT_OUT { - CK_OBJECT_HANDLE hMacSecret; - CK_OBJECT_HANDLE hKey; - CK_BYTE_PTR pIV; + CK_OBJECT_HANDLE hMacSecret; + CK_OBJECT_HANDLE hKey; + CK_BYTE_PTR pIV; } CK_WTLS_KEY_MAT_OUT; typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR; typedef struct CK_WTLS_KEY_MAT_PARAMS { - CK_MECHANISM_TYPE DigestMechanism; - CK_ULONG ulMacSizeInBits; - CK_ULONG ulKeySizeInBits; - CK_ULONG ulIVSizeInBits; - CK_ULONG ulSequenceNumber; - CK_BBOOL bIsExport; - CK_WTLS_RANDOM_DATA RandomInfo; - CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial; + CK_MECHANISM_TYPE DigestMechanism; + CK_ULONG ulMacSizeInBits; + CK_ULONG ulKeySizeInBits; + CK_ULONG ulIVSizeInBits; + CK_ULONG ulSequenceNumber; + CK_BBOOL bIsExport; + CK_WTLS_RANDOM_DATA RandomInfo; + CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial; } CK_WTLS_KEY_MAT_PARAMS; typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR; typedef struct CK_CMS_SIG_PARAMS { - CK_OBJECT_HANDLE certificateHandle; - CK_MECHANISM_PTR pSigningMechanism; - CK_MECHANISM_PTR pDigestMechanism; - CK_UTF8CHAR_PTR pContentType; - CK_BYTE_PTR pRequestedAttributes; - CK_ULONG ulRequestedAttributesLen; - CK_BYTE_PTR pRequiredAttributes; - CK_ULONG ulRequiredAttributesLen; + CK_OBJECT_HANDLE certificateHandle; + CK_MECHANISM_PTR pSigningMechanism; + CK_MECHANISM_PTR pDigestMechanism; + CK_UTF8CHAR_PTR pContentType; + CK_BYTE_PTR pRequestedAttributes; + CK_ULONG ulRequestedAttributesLen; + CK_BYTE_PTR pRequiredAttributes; + CK_ULONG ulRequiredAttributesLen; } CK_CMS_SIG_PARAMS; typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR; typedef struct CK_KEY_DERIVATION_STRING_DATA { - CK_BYTE_PTR pData; - CK_ULONG ulLen; + CK_BYTE_PTR pData; + CK_ULONG ulLen; } CK_KEY_DERIVATION_STRING_DATA; typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \ - CK_KEY_DERIVATION_STRING_DATA_PTR; + CK_KEY_DERIVATION_STRING_DATA_PTR; /* The CK_EXTRACT_PARAMS is used for the @@ -1715,7 +1920,7 @@ typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR; typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE; typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR \ - CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR; + CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR; #define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001UL #define CKP_PKCS5_PBKD2_HMAC_GOSTR3411 0x00000002UL @@ -1733,7 +1938,7 @@ typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR \ typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE; typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR \ - CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR; + CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR; /* The following salt value sources are defined in PKCS #5 v2.0. */ #define CKZ_SALT_SPECIFIED 0x00000001UL @@ -1742,15 +1947,15 @@ typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR \ * parameters to the CKM_PKCS5_PBKD2 mechanism. */ typedef struct CK_PKCS5_PBKD2_PARAMS { - CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource; - CK_VOID_PTR pSaltSourceData; - CK_ULONG ulSaltSourceDataLen; - CK_ULONG iterations; - CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf; - CK_VOID_PTR pPrfData; - CK_ULONG ulPrfDataLen; - CK_UTF8CHAR_PTR pPassword; - CK_ULONG_PTR ulPasswordLen; + CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource; + CK_VOID_PTR pSaltSourceData; + CK_ULONG ulSaltSourceDataLen; + CK_ULONG iterations; + CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf; + CK_VOID_PTR pPrfData; + CK_ULONG ulPrfDataLen; + CK_UTF8CHAR_PTR pPassword; + CK_ULONG_PTR ulPasswordLen; } CK_PKCS5_PBKD2_PARAMS; typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR; @@ -1760,15 +1965,15 @@ typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR; * noting that the ulPasswordLen field is a CK_ULONG and not a CK_ULONG_PTR. */ typedef struct CK_PKCS5_PBKD2_PARAMS2 { - CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource; - CK_VOID_PTR pSaltSourceData; - CK_ULONG ulSaltSourceDataLen; - CK_ULONG iterations; - CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf; - CK_VOID_PTR pPrfData; - CK_ULONG ulPrfDataLen; - CK_UTF8CHAR_PTR pPassword; - CK_ULONG ulPasswordLen; + CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource; + CK_VOID_PTR pSaltSourceData; + CK_ULONG ulSaltSourceDataLen; + CK_ULONG iterations; + CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf; + CK_VOID_PTR pPrfData; + CK_ULONG ulPrfDataLen; + CK_UTF8CHAR_PTR pPassword; + CK_ULONG ulPasswordLen; } CK_PKCS5_PBKD2_PARAMS2; typedef CK_PKCS5_PBKD2_PARAMS2 CK_PTR CK_PKCS5_PBKD2_PARAMS2_PTR; @@ -1778,22 +1983,22 @@ typedef CK_OTP_PARAM_TYPE CK_PARAM_TYPE; /* backward compatibility */ typedef struct CK_OTP_PARAM { CK_OTP_PARAM_TYPE type; - CK_VOID_PTR pValue; - CK_ULONG ulValueLen; + CK_VOID_PTR pValue; + CK_ULONG ulValueLen; } CK_OTP_PARAM; typedef CK_OTP_PARAM CK_PTR CK_OTP_PARAM_PTR; typedef struct CK_OTP_PARAMS { CK_OTP_PARAM_PTR pParams; - CK_ULONG ulCount; + CK_ULONG ulCount; } CK_OTP_PARAMS; typedef CK_OTP_PARAMS CK_PTR CK_OTP_PARAMS_PTR; typedef struct CK_OTP_SIGNATURE_INFO { CK_OTP_PARAM_PTR pParams; - CK_ULONG ulCount; + CK_ULONG ulCount; } CK_OTP_SIGNATURE_INFO; typedef CK_OTP_SIGNATURE_INFO CK_PTR CK_OTP_SIGNATURE_INFO_PTR; @@ -1815,106 +2020,135 @@ typedef CK_OTP_SIGNATURE_INFO CK_PTR CK_OTP_SIGNATURE_INFO_PTR; #define CKF_USER_FRIENDLY_OTP 0x00000020UL typedef struct CK_KIP_PARAMS { - CK_MECHANISM_PTR pMechanism; - CK_OBJECT_HANDLE hKey; - CK_BYTE_PTR pSeed; - CK_ULONG ulSeedLen; + CK_MECHANISM_PTR pMechanism; + CK_OBJECT_HANDLE hKey; + CK_BYTE_PTR pSeed; + CK_ULONG ulSeedLen; } CK_KIP_PARAMS; typedef CK_KIP_PARAMS CK_PTR CK_KIP_PARAMS_PTR; typedef struct CK_AES_CTR_PARAMS { CK_ULONG ulCounterBits; - CK_BYTE cb[16]; + CK_BYTE cb[16]; } CK_AES_CTR_PARAMS; typedef CK_AES_CTR_PARAMS CK_PTR CK_AES_CTR_PARAMS_PTR; typedef struct CK_GCM_PARAMS { - CK_BYTE_PTR pIv; - CK_ULONG ulIvLen; - CK_ULONG ulIvBits; - CK_BYTE_PTR pAAD; - CK_ULONG ulAADLen; - CK_ULONG ulTagBits; + CK_BYTE_PTR pIv; + CK_ULONG ulIvLen; + CK_ULONG ulIvBits; + CK_BYTE_PTR pAAD; + CK_ULONG ulAADLen; + CK_ULONG ulTagBits; } CK_GCM_PARAMS; typedef CK_GCM_PARAMS CK_PTR CK_GCM_PARAMS_PTR; +typedef CK_ULONG CK_GENERATOR_FUNCTION; +#define CKG_NO_GENERATE 0x00000000UL +#define CKG_GENERATE 0x00000001UL +#define CKG_GENERATE_COUNTER 0x00000002UL +#define CKG_GENERATE_RANDOM 0x00000003UL + +typedef struct CK_GCM_MESSAGE_PARAMS { + CK_BYTE_PTR pIv; + CK_ULONG ulIvLen; + CK_ULONG ulIvFixedBits; + CK_GENERATOR_FUNCTION ivGenerator; + CK_BYTE_PTR pTag; + CK_ULONG ulTagBits; +} CK_GCM_MESSAGE_PARAMS; + +typedef CK_GCM_MESSAGE_PARAMS CK_GCM_MESSAGE_PARAMS_PTR; + typedef struct CK_CCM_PARAMS { - CK_ULONG ulDataLen; - CK_BYTE_PTR pNonce; - CK_ULONG ulNonceLen; - CK_BYTE_PTR pAAD; - CK_ULONG ulAADLen; - CK_ULONG ulMACLen; + CK_ULONG ulDataLen; + CK_BYTE_PTR pNonce; + CK_ULONG ulNonceLen; + CK_BYTE_PTR pAAD; + CK_ULONG ulAADLen; + CK_ULONG ulMACLen; } CK_CCM_PARAMS; typedef CK_CCM_PARAMS CK_PTR CK_CCM_PARAMS_PTR; +typedef struct CK_CCM_MESSAGE_PARAMS { + CK_ULONG ulDataLen; /*plaintext or ciphertext*/ + CK_BYTE_PTR pNonce; + CK_ULONG ulNonceLen; + CK_ULONG ulNonceFixedBits; + CK_GENERATOR_FUNCTION nonceGenerator; + CK_BYTE_PTR pMAC; + CK_ULONG ulMACLen; +} CK_CCM_MESSAGE_PARAMS; + +typedef CK_CCM_MESSAGE_PARAMS CK_CCM_MESSAGE_PARAMS_PTR; + /* Deprecated. Use CK_GCM_PARAMS */ typedef struct CK_AES_GCM_PARAMS { - CK_BYTE_PTR pIv; - CK_ULONG ulIvLen; - CK_ULONG ulIvBits; - CK_BYTE_PTR pAAD; - CK_ULONG ulAADLen; - CK_ULONG ulTagBits; + CK_BYTE_PTR pIv; + CK_ULONG ulIvLen; + CK_ULONG ulIvBits; + CK_BYTE_PTR pAAD; + CK_ULONG ulAADLen; + CK_ULONG ulTagBits; } CK_AES_GCM_PARAMS; typedef CK_AES_GCM_PARAMS CK_PTR CK_AES_GCM_PARAMS_PTR; /* Deprecated. Use CK_CCM_PARAMS */ typedef struct CK_AES_CCM_PARAMS { - CK_ULONG ulDataLen; - CK_BYTE_PTR pNonce; - CK_ULONG ulNonceLen; - CK_BYTE_PTR pAAD; - CK_ULONG ulAADLen; - CK_ULONG ulMACLen; + CK_ULONG ulDataLen; + CK_BYTE_PTR pNonce; + CK_ULONG ulNonceLen; + CK_BYTE_PTR pAAD; + CK_ULONG ulAADLen; + CK_ULONG ulMACLen; } CK_AES_CCM_PARAMS; typedef CK_AES_CCM_PARAMS CK_PTR CK_AES_CCM_PARAMS_PTR; typedef struct CK_CAMELLIA_CTR_PARAMS { - CK_ULONG ulCounterBits; - CK_BYTE cb[16]; + CK_ULONG ulCounterBits; + CK_BYTE cb[16]; } CK_CAMELLIA_CTR_PARAMS; typedef CK_CAMELLIA_CTR_PARAMS CK_PTR CK_CAMELLIA_CTR_PARAMS_PTR; typedef struct CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS { - CK_BYTE iv[16]; - CK_BYTE_PTR pData; - CK_ULONG length; + CK_BYTE iv[16]; + CK_BYTE_PTR pData; + CK_ULONG length; } CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS; typedef CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR \ - CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS_PTR; + CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS_PTR; typedef struct CK_ARIA_CBC_ENCRYPT_DATA_PARAMS { - CK_BYTE iv[16]; - CK_BYTE_PTR pData; - CK_ULONG length; + CK_BYTE iv[16]; + CK_BYTE_PTR pData; + CK_ULONG length; } CK_ARIA_CBC_ENCRYPT_DATA_PARAMS; typedef CK_ARIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR \ - CK_ARIA_CBC_ENCRYPT_DATA_PARAMS_PTR; + CK_ARIA_CBC_ENCRYPT_DATA_PARAMS_PTR; typedef struct CK_DSA_PARAMETER_GEN_PARAM { - CK_MECHANISM_TYPE hash; - CK_BYTE_PTR pSeed; - CK_ULONG ulSeedLen; - CK_ULONG ulIndex; + CK_MECHANISM_TYPE hash; + CK_BYTE_PTR pSeed; + CK_ULONG ulSeedLen; + CK_ULONG ulIndex; } CK_DSA_PARAMETER_GEN_PARAM; typedef CK_DSA_PARAMETER_GEN_PARAM CK_PTR CK_DSA_PARAMETER_GEN_PARAM_PTR; typedef struct CK_ECDH_AES_KEY_WRAP_PARAMS { - CK_ULONG ulAESKeyBits; - CK_EC_KDF_TYPE kdf; - CK_ULONG ulSharedDataLen; - CK_BYTE_PTR pSharedData; + CK_ULONG ulAESKeyBits; + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; } CK_ECDH_AES_KEY_WRAP_PARAMS; typedef CK_ECDH_AES_KEY_WRAP_PARAMS CK_PTR CK_ECDH_AES_KEY_WRAP_PARAMS_PTR; @@ -1924,81 +2158,287 @@ typedef CK_ULONG CK_JAVA_MIDP_SECURITY_DOMAIN; typedef CK_ULONG CK_CERTIFICATE_CATEGORY; typedef struct CK_RSA_AES_KEY_WRAP_PARAMS { - CK_ULONG ulAESKeyBits; - CK_RSA_PKCS_OAEP_PARAMS_PTR pOAEPParams; + CK_ULONG ulAESKeyBits; + CK_RSA_PKCS_OAEP_PARAMS_PTR pOAEPParams; } CK_RSA_AES_KEY_WRAP_PARAMS; typedef CK_RSA_AES_KEY_WRAP_PARAMS CK_PTR CK_RSA_AES_KEY_WRAP_PARAMS_PTR; typedef struct CK_TLS12_MASTER_KEY_DERIVE_PARAMS { - CK_SSL3_RANDOM_DATA RandomInfo; - CK_VERSION_PTR pVersion; - CK_MECHANISM_TYPE prfHashMechanism; + CK_SSL3_RANDOM_DATA RandomInfo; + CK_VERSION_PTR pVersion; + CK_MECHANISM_TYPE prfHashMechanism; } CK_TLS12_MASTER_KEY_DERIVE_PARAMS; typedef CK_TLS12_MASTER_KEY_DERIVE_PARAMS CK_PTR \ - CK_TLS12_MASTER_KEY_DERIVE_PARAMS_PTR; + CK_TLS12_MASTER_KEY_DERIVE_PARAMS_PTR; typedef struct CK_TLS12_KEY_MAT_PARAMS { - CK_ULONG ulMacSizeInBits; - CK_ULONG ulKeySizeInBits; - CK_ULONG ulIVSizeInBits; - CK_BBOOL bIsExport; - CK_SSL3_RANDOM_DATA RandomInfo; - CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial; - CK_MECHANISM_TYPE prfHashMechanism; + CK_ULONG ulMacSizeInBits; + CK_ULONG ulKeySizeInBits; + CK_ULONG ulIVSizeInBits; + CK_BBOOL bIsExport; + CK_SSL3_RANDOM_DATA RandomInfo; + CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial; + CK_MECHANISM_TYPE prfHashMechanism; } CK_TLS12_KEY_MAT_PARAMS; typedef CK_TLS12_KEY_MAT_PARAMS CK_PTR CK_TLS12_KEY_MAT_PARAMS_PTR; typedef struct CK_TLS_KDF_PARAMS { - CK_MECHANISM_TYPE prfMechanism; - CK_BYTE_PTR pLabel; - CK_ULONG ulLabelLength; - CK_SSL3_RANDOM_DATA RandomInfo; - CK_BYTE_PTR pContextData; - CK_ULONG ulContextDataLength; + CK_MECHANISM_TYPE prfMechanism; + CK_BYTE_PTR pLabel; + CK_ULONG ulLabelLength; + CK_SSL3_RANDOM_DATA RandomInfo; + CK_BYTE_PTR pContextData; + CK_ULONG ulContextDataLength; } CK_TLS_KDF_PARAMS; typedef CK_TLS_KDF_PARAMS CK_PTR CK_TLS_KDF_PARAMS_PTR; typedef struct CK_TLS_MAC_PARAMS { - CK_MECHANISM_TYPE prfHashMechanism; - CK_ULONG ulMacLength; - CK_ULONG ulServerOrClient; + CK_MECHANISM_TYPE prfHashMechanism; + CK_ULONG ulMacLength; + CK_ULONG ulServerOrClient; } CK_TLS_MAC_PARAMS; typedef CK_TLS_MAC_PARAMS CK_PTR CK_TLS_MAC_PARAMS_PTR; typedef struct CK_GOSTR3410_DERIVE_PARAMS { - CK_EC_KDF_TYPE kdf; - CK_BYTE_PTR pPublicData; - CK_ULONG ulPublicDataLen; - CK_BYTE_PTR pUKM; - CK_ULONG ulUKMLen; + CK_EC_KDF_TYPE kdf; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pUKM; + CK_ULONG ulUKMLen; } CK_GOSTR3410_DERIVE_PARAMS; typedef CK_GOSTR3410_DERIVE_PARAMS CK_PTR CK_GOSTR3410_DERIVE_PARAMS_PTR; typedef struct CK_GOSTR3410_KEY_WRAP_PARAMS { - CK_BYTE_PTR pWrapOID; - CK_ULONG ulWrapOIDLen; - CK_BYTE_PTR pUKM; - CK_ULONG ulUKMLen; - CK_OBJECT_HANDLE hKey; + CK_BYTE_PTR pWrapOID; + CK_ULONG ulWrapOIDLen; + CK_BYTE_PTR pUKM; + CK_ULONG ulUKMLen; + CK_OBJECT_HANDLE hKey; } CK_GOSTR3410_KEY_WRAP_PARAMS; typedef CK_GOSTR3410_KEY_WRAP_PARAMS CK_PTR CK_GOSTR3410_KEY_WRAP_PARAMS_PTR; typedef struct CK_SEED_CBC_ENCRYPT_DATA_PARAMS { - CK_BYTE iv[16]; - CK_BYTE_PTR pData; - CK_ULONG length; + CK_BYTE iv[16]; + CK_BYTE_PTR pData; + CK_ULONG length; } CK_SEED_CBC_ENCRYPT_DATA_PARAMS; typedef CK_SEED_CBC_ENCRYPT_DATA_PARAMS CK_PTR \ - CK_SEED_CBC_ENCRYPT_DATA_PARAMS_PTR; + CK_SEED_CBC_ENCRYPT_DATA_PARAMS_PTR; -#endif /* _PKCS11T_H_ */ +/* + * New PKCS 11 v3.0 data structures. + */ + +typedef CK_ULONG CK_PROFILE_ID; +typedef CK_PROFILE_ID CK_PTR CK_PROFILE_ID_PTR; + +/* Typedefs for Flexible KDF */ +typedef CK_ULONG CK_PRF_DATA_TYPE; +typedef CK_MECHANISM_TYPE CK_SP800_108_PRF_TYPE; +#define CK_SP800_108_ITERATION_VARIABLE 0x00000001UL +#define CK_SP800_108_OPTIONAL_COUNTER 0x00000002UL +#define CK_SP800_108_DKM_LENGTH 0x00000003UL +#define CK_SP800_108_BYTE_ARRAY 0x00000004UL +#define CK_SP800_108_COUNTER CK_SP800_108_OPTIONAL_COUNTER + +typedef struct CK_PRF_DATA_PARAM +{ + CK_PRF_DATA_TYPE type; + CK_VOID_PTR pValue; + CK_ULONG ulValueLen; +} CK_PRF_DATA_PARAM; + +typedef CK_PRF_DATA_PARAM CK_PTR CK_PRF_DATA_PARAM_PTR; + + +typedef struct CK_SP800_108_COUNTER_FORMAT +{ + CK_BBOOL bLittleEndian; + CK_ULONG ulWidthInBits; +} CK_SP800_108_COUNTER_FORMAT; + +typedef CK_SP800_108_COUNTER_FORMAT CK_PTR CK_SP800_108_COUNTER_FORMAT_PTR; + +typedef CK_ULONG CK_SP800_108_DKM_LENGTH_METHOD; +#define CK_SP800_108_DKM_LENGTH_SUM_OF_KEYS 0x00000001UL +#define CK_SP800_108_DKM_LENGTH_SUM_OF_SEGMENTS 0x00000002UL + +typedef struct CK_SP800_108_DKM_LENGTH_FORMAT +{ + CK_SP800_108_DKM_LENGTH_METHOD dkmLengthMethod; + CK_BBOOL bLittleEndian; + CK_ULONG ulWidthInBits; +} CK_SP800_108_DKM_LENGTH_FORMAT; + +typedef CK_SP800_108_DKM_LENGTH_FORMAT \ + CK_PTR CK_SP800_108_DKM_LENGTH_FORMAT_PTR; + +typedef struct CK_DERIVED_KEY +{ + CK_ATTRIBUTE_PTR pTemplate; + CK_ULONG ulAttributeCount; + CK_OBJECT_HANDLE_PTR phKey; +} CK_DERIVED_KEY; + +typedef CK_DERIVED_KEY CK_PTR CK_DERIVED_KEY_PTR; + +typedef struct CK_SP800_108_KDF_PARAMS +{ + CK_SP800_108_PRF_TYPE prfType; + CK_ULONG ulNumberOfDataParams; + CK_PRF_DATA_PARAM_PTR pDataParams; + CK_ULONG ulAdditionalDerivedKeys; + CK_DERIVED_KEY_PTR pAdditionalDerivedKeys; +} CK_SP800_108_KDF_PARAMS; + +typedef CK_SP800_108_KDF_PARAMS CK_PTR CK_SP800_108_KDF_PARAMS_PTR; + +typedef struct CK_SP800_108_FEEDBACK_KDF_PARAMS +{ + CK_SP800_108_PRF_TYPE prfType; + CK_ULONG ulNumberOfDataParams; + CK_PRF_DATA_PARAM_PTR pDataParams; + CK_ULONG ulIVLen; + CK_BYTE_PTR pIV; + CK_ULONG ulAdditionalDerivedKeys; + CK_DERIVED_KEY_PTR pAdditionalDerivedKeys; +} CK_SP800_108_FEEDBACK_KDF_PARAMS; + +typedef CK_SP800_108_FEEDBACK_KDF_PARAMS \ + CK_PTR CK_SP800_108_FEEDBACK_KDF_PARAMS_PTR; + +/* EDDSA */ +typedef struct CK_EDDSA_PARAMS { + CK_BBOOL phFlag; + CK_ULONG ulContextDataLen; + CK_BYTE_PTR pContextData; +} CK_EDDSA_PARAMS; + +typedef CK_EDDSA_PARAMS CK_PTR CK_EDDSA_PARAMS_PTR; + +/* Extended ChaCha20/Salsa20 support*/ +typedef struct CK_CHACHA20_PARAMS { + CK_BYTE_PTR pBlockCounter; + CK_ULONG blockCounterBits; + CK_BYTE_PTR pNonce; + CK_ULONG ulNonceBits; +} CK_CHACHA20_PARAMS; + +typedef CK_CHACHA20_PARAMS CK_PTR CK_CHACHA20_PARAMS_PTR; + +typedef struct CK_SALSA20_PARAMS { + CK_BYTE_PTR pBlockCounter; + CK_BYTE_PTR pNonce; + CK_ULONG ulNonceBits; +} CK_SALSA20_PARAMS; + +typedef CK_SALSA20_PARAMS CK_PTR CK_SALSA20_PARAMS_PTR; + +typedef struct CK_SALSA20_CHACHA20_POLY1305_PARAMS { + CK_BYTE_PTR pNonce; + CK_ULONG ulNonceLen; + CK_BYTE_PTR pAAD; + CK_ULONG ulAADLen; +} CK_SALSA20_CHACHA20_POLY1305_PARAMS; + +typedef CK_SALSA20_CHACHA20_POLY1305_PARAMS \ + CK_PTR CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR; + +typedef struct CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS { + CK_BYTE_PTR pNonce; + CK_ULONG ulNonceLen; + CK_BYTE_PTR pTag; +} CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS; + +typedef CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS \ + CK_PTR CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS_PTR; + +typedef CK_ULONG CK_X3DH_KDF_TYPE; +typedef CK_X3DH_KDF_TYPE CK_PTR CK_X3DH_KDF_TYPE_PTR; + +/* X3dh, ratchet */ +typedef struct CK_X3DH_INITIATE_PARAMS { + CK_X3DH_KDF_TYPE kdf; + CK_OBJECT_HANDLE pPeer_identity; + CK_OBJECT_HANDLE pPeer_prekey; + CK_BYTE_PTR pPrekey_signature; + CK_BYTE_PTR pOnetime_key; + CK_OBJECT_HANDLE pOwn_identity; + CK_OBJECT_HANDLE pOwn_ephemeral; +} CK_X3DH_INITIATE_PARAMS; + +typedef struct CK_X3DH_RESPOND_PARAMS { + CK_X3DH_KDF_TYPE kdf; + CK_BYTE_PTR pIdentity_id; + CK_BYTE_PTR pPrekey_id; + CK_BYTE_PTR pOnetime_id; + CK_OBJECT_HANDLE pInitiator_identity; + CK_BYTE_PTR pInitiator_ephemeral; +} CK_X3DH_RESPOND_PARAMS; + +typedef CK_ULONG CK_X2RATCHET_KDF_TYPE; +typedef CK_X2RATCHET_KDF_TYPE CK_PTR CK_X2RATCHET_KDF_TYPE_PTR; + +typedef struct CK_X2RATCHET_INITIALIZE_PARAMS { + CK_BYTE_PTR sk; + CK_OBJECT_HANDLE peer_public_prekey; + CK_OBJECT_HANDLE peer_public_identity; + CK_OBJECT_HANDLE own_public_identity; + CK_BBOOL bEncryptedHeader; + CK_ULONG eCurve; + CK_MECHANISM_TYPE aeadMechanism; + CK_X2RATCHET_KDF_TYPE kdfMechanism; +} CK_X2RATCHET_INITIALIZE_PARAMS; + +typedef CK_X2RATCHET_INITIALIZE_PARAMS \ + CK_PTR CK_X2RATCHET_INITIALIZE_PARAMS_PTR; + +typedef struct CK_X2RATCHET_RESPOND_PARAMS { + CK_BYTE_PTR sk; + CK_OBJECT_HANDLE own_prekey; + CK_OBJECT_HANDLE initiator_identity; + CK_OBJECT_HANDLE own_public_identity; + CK_BBOOL bEncryptedHeader; + CK_ULONG eCurve; + CK_MECHANISM_TYPE aeadMechanism; + CK_X2RATCHET_KDF_TYPE kdfMechanism; +} CK_X2RATCHET_RESPOND_PARAMS; +typedef CK_X2RATCHET_RESPOND_PARAMS \ + CK_PTR CK_X2RATCHET_RESPOND_PARAMS_PTR; + +typedef CK_ULONG CK_XEDDSA_HASH_TYPE; +typedef CK_XEDDSA_HASH_TYPE CK_PTR CK_XEDDSA_HASH_TYPE_PTR; + +/* XEDDSA */ +typedef struct CK_XEDDSA_PARAMS { + CK_XEDDSA_HASH_TYPE hash; +} CK_XEDDSA_PARAMS; +typedef CK_XEDDSA_PARAMS CK_PTR CK_XEDDSA_PARAMS_PTR; + +typedef struct CK_HKDF_PARAMS { + CK_BBOOL bExtract; + CK_BBOOL bExpand; + CK_MECHANISM_TYPE prfHashMechanism; + CK_ULONG ulSaltType; + CK_BYTE_PTR pSalt; + CK_ULONG ulSaltLen; + CK_OBJECT_HANDLE hSaltKey; + CK_BYTE_PTR pInfo; + CK_ULONG ulInfoLen; +} CK_HKDF_PARAMS; +typedef CK_HKDF_PARAMS CK_PTR CK_HKDF_PARAMS_PTR; + +#define CKF_HKDF_SALT_NULL 0x00000001UL +#define CKF_HKDF_SALT_DATA 0x00000002UL +#define CKF_HKDF_SALT_KEY 0x00000004UL +#endif /* _PKCS11T_H_ */ diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java index 637a7a284bf..0e73f291ac4 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java @@ -400,7 +400,7 @@ static boolean doBinTest(int cond, double a, double b) { /*package-private*/ @ForceInline static long toBits(double e) { - return Double.doubleToLongBits(e); + return Double.doubleToRawLongBits(e); } /*package-private*/ diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java index d85e3628d88..f43ef9e96fb 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java @@ -400,7 +400,7 @@ static boolean doBinTest(int cond, float a, float b) { /*package-private*/ @ForceInline static long toBits(float e) { - return Float.floatToIntBits(e); + return Float.floatToRawIntBits(e); } /*package-private*/ diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template index 15c32cb01c8..54399c82cfd 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template @@ -404,7 +404,7 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { /*package-private*/ @ForceInline static long toBits($type$ e) { - return {#if[FP]? $Type$.$type$To$Bitstype$Bits(e): e}; + return {#if[FP]? $Type$.$type$ToRaw$Bitstype$Bits(e): e}; } /*package-private*/ diff --git a/src/jdk.jfr/share/classes/jdk/jfr/EventSettings.java b/src/jdk.jfr/share/classes/jdk/jfr/EventSettings.java index f6bdbd8bbbb..f950fd2207e 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/EventSettings.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/EventSettings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,8 @@ import java.time.Duration; import java.util.Map; +import jdk.jfr.internal.management.EventSettingsModifier; + /** * Convenience class for applying event settings to a recording. *

    @@ -55,6 +57,26 @@ */ public abstract class EventSettings { + // Used to provide EventSettings for jdk.management.jfr module + static class DelegatedEventSettings extends EventSettings { + private final EventSettingsModifier delegate; + + DelegatedEventSettings(EventSettingsModifier modifier) { + this.delegate = modifier; + } + + @Override + public EventSettings with(String name, String value) { + delegate.with(name, value); + return this; + } + + @Override + Map toMap() { + return delegate.toMap(); + } + } + // package private EventSettings() { } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java index 6453e18f407..b340a5ffb40 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java @@ -37,6 +37,7 @@ import jdk.jfr.internal.PrivateAccess; import jdk.jfr.internal.Type; import jdk.jfr.internal.Utils; +import jdk.jfr.internal.management.EventSettingsModifier; /** * Permission for controlling access to Flight Recorder. @@ -197,6 +198,11 @@ public PlatformRecorder getPlatformRecorder() { public AccessControlContext getContext(SettingControl settingControl) { return settingControl.getContext(); } + + @Override + public EventSettings newEventSettings(EventSettingsModifier esm) { + return new EventSettings.DelegatedEventSettings(esm); + } } /** diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java index c8789826016..d1312eefc8f 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java @@ -31,6 +31,7 @@ import java.security.AccessController; import java.time.Duration; import java.time.Instant; +import java.util.Collections; import java.util.Objects; import java.util.function.Consumer; @@ -137,7 +138,7 @@ public interface EventStream extends AutoCloseable { */ public static EventStream openRepository() throws IOException { Utils.checkAccessFlightRecorder(); - return new EventDirectoryStream(AccessController.getContext(), null, SecuritySupport.PRIVILEGED, null); + return new EventDirectoryStream(AccessController.getContext(), null, SecuritySupport.PRIVILEGED, null, Collections.emptyList()); } /** @@ -160,7 +161,7 @@ public static EventStream openRepository() throws IOException { public static EventStream openRepository(Path directory) throws IOException { Objects.nonNull(directory); AccessControlContext acc = AccessController.getContext(); - return new EventDirectoryStream(acc, directory, FileAccess.UNPRIVILEGED, null); + return new EventDirectoryStream(acc, directory, FileAccess.UNPRIVILEGED, null, Collections.emptyList()); } /** @@ -182,6 +183,22 @@ static EventStream openFile(Path file) throws IOException { return new EventFileStream(AccessController.getContext(), file); } + /** + * Registers an action to perform when new metadata arrives in the stream. + * + * The event type of an event always arrives sometime before the actual event. + * The action must be registered before the stream is started. + * + * @implSpec The default implementation of this method is empty. + * + * @param action to perform, not {@code null} + * + * @throws IllegalStateException if an action is added after the stream has + * started + */ + default void onMetadata(Consumer action) { + } + /** * Registers an action to perform on all events in the stream. * diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/MetadataEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/MetadataEvent.java new file mode 100644 index 00000000000..19cb75256f3 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/MetadataEvent.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jfr.consumer; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jdk.jfr.Configuration; +import jdk.jfr.EventType; + +/** + * Event that contains information about event types and configurations. + * + * @since 16 + */ +public final class MetadataEvent { + private final List current; + private final List previous; + private final List configurations; + private List added; + private List removed; + + /* package private */ + MetadataEvent(List previous, List current, List configs) { + this.previous = previous; + this.current = current; + this.configurations = configs; + } + + /** + * Returns a list of the current event types being used. + * + * @return an immutable list of event types, not {@code null} + */ + public final List getEventTypes() { + return Collections.unmodifiableList(current); + } + + /** + * Returns a list of added event types since the last metadata event. + *

    + * The delta will be from the last metadata event. If no metadata event has been + * emitted earlier, all known event types will be in the list. + * + * @return an immutable list of added event types, not {@code null} + */ + public final List getAddedEventTypes() { + if (added == null) { + calculateDelta(); + } + return added; + } + + /** + * Returns a list of removed event types since the last metadata event. + *

    + * The delta will be from the last metadata event. If no metadata event has been + * emitted earlier, the list will be empty. + * + * @return an immutable list of added event types, not {@code null} + */ + public final List getRemovedEventTypes() { + if (removed == null) { + calculateDelta(); + } + return removed; + } + + /** + * Returns a list of configurations. + * + * @return an immutable list of configurations, not {@code null} + */ + public List getConfigurations() { + return configurations; + } + + private void calculateDelta() { + List added = new ArrayList<>(); + Map previousSet = new HashMap<>(previous.size()); + for (EventType eventType : previous) { + previousSet.put(eventType.getId(), eventType); + } + for (EventType eventType : current) { + EventType t = previousSet.remove(eventType.getId()); + if (t == null) { + added.add(eventType); + } + } + this.removed = Collections.unmodifiableList(new ArrayList<>(previousSet.values())); + this.added = Collections.unmodifiableList(added); + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java index b6f310dafb1..5bab6205db4 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java @@ -34,15 +34,19 @@ import java.util.Comparator; import java.util.List; import java.util.Objects; +import java.util.function.Consumer; +import jdk.jfr.Configuration; +import jdk.jfr.EventType; import jdk.jfr.Timespan; import jdk.jfr.Timestamp; import jdk.jfr.ValueDescriptor; -import jdk.jfr.internal.consumer.JdkJfrConsumer; -import jdk.jfr.internal.consumer.ObjectFactory; import jdk.jfr.internal.PrivateAccess; import jdk.jfr.internal.Type; +import jdk.jfr.internal.consumer.EventDirectoryStream; +import jdk.jfr.internal.consumer.JdkJfrConsumer; import jdk.jfr.internal.consumer.ObjectContext; +import jdk.jfr.internal.consumer.ObjectFactory; import jdk.jfr.internal.tool.PrettyWriter; /** @@ -136,6 +140,12 @@ public void setEndTicks(RecordedEvent event, long endTicks) { public Object[] eventValues(RecordedEvent event) { return event.objects; } + + @Override + public MetadataEvent newMetadataEvent(List previous, List current, + List configurations) { + return new MetadataEvent(previous, current, configurations); + } }; JdkJfrConsumer.setAccess(access); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java index c5c749c3026..3c6a37d29f4 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java @@ -30,6 +30,8 @@ import java.security.AccessController; import java.time.Duration; import java.time.Instant; +import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.function.Consumer; @@ -43,6 +45,7 @@ import jdk.jfr.internal.SecuritySupport; import jdk.jfr.internal.Utils; import jdk.jfr.internal.consumer.EventDirectoryStream; +import jdk.jfr.internal.consumer.JdkJfrConsumer; /** * A recording stream produces events from the current JVM (Java Virtual @@ -85,13 +88,21 @@ public RecordingStream() { this.recording = new Recording(); try { PlatformRecording pr = PrivateAccess.getInstance().getPlatformRecording(recording); - this.directoryStream = new EventDirectoryStream(acc, null, SecuritySupport.PRIVILEGED, pr); + this.directoryStream = new EventDirectoryStream(acc, null, SecuritySupport.PRIVILEGED, pr, configurations()); } catch (IOException ioe) { this.recording.close(); throw new IllegalStateException(ioe.getMessage()); } } + private List configurations() { + try { + return Configuration.getConfigurations(); + } catch (Exception e) { + return Collections.emptyList(); + } + } + /** * Creates a recording stream using settings from a configuration. *

    @@ -361,4 +372,9 @@ public void awaitTermination(Duration timeout) throws InterruptedException { public void awaitTermination() throws InterruptedException { directoryStream.awaitTermination(); } + + @Override + public void onMetadata(Consumer action) { + directoryStream.onMetadata(action); + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java index 51bbe7a6252..1c27a85b812 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java @@ -86,6 +86,7 @@ public final class PlatformRecording implements AutoCloseable { private boolean shouldWriteActiveRecordingEvent = true; private Duration flushInterval = Duration.ofSeconds(1); private long finalStartChunkNanos = Long.MIN_VALUE; + private long startNanos = -1; PlatformRecording(PlatformRecorder recorder, long id) { // Typically the access control context is taken @@ -103,7 +104,6 @@ public final class PlatformRecording implements AutoCloseable { public long start() { RecordingState oldState; RecordingState newState; - long startNanos = -1; synchronized (recorder) { oldState = getState(); if (!Utils.isBefore(state, RecordingState.RUNNING)) { @@ -826,6 +826,10 @@ public long getStreamIntervalMillis() { } } + public long getStartNanos() { + return startNanos; + } + public long getFinalChunkStartNanos() { return finalStartChunkNanos; } @@ -833,4 +837,18 @@ public long getFinalChunkStartNanos() { public void setFinalStartnanos(long chunkStartNanos) { this.finalStartChunkNanos = chunkStartNanos; } + + public void removeBefore(Instant timestamp) { + synchronized (recorder) { + while (!chunks.isEmpty()) { + RepositoryChunk oldestChunk = chunks.peek(); + if (!oldestChunk.getEndTime().isBefore(timestamp)) { + return; + } + chunks.removeFirst(); + removed(oldestChunk); + } + } + + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PrivateAccess.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PrivateAccess.java index 326c8e55f28..1028fab8ddf 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PrivateAccess.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PrivateAccess.java @@ -31,12 +31,14 @@ import jdk.jfr.AnnotationElement; import jdk.jfr.Configuration; +import jdk.jfr.EventSettings; import jdk.jfr.EventType; import jdk.jfr.FlightRecorderPermission; import jdk.jfr.Recording; import jdk.jfr.SettingControl; import jdk.jfr.SettingDescriptor; import jdk.jfr.ValueDescriptor; +import jdk.jfr.internal.management.EventSettingsModifier; /** * Provides access to package private function in jdk.jfr. @@ -98,4 +100,6 @@ public static void setPrivateAccess(PrivateAccess pa) { public abstract PlatformRecorder getPlatformRecorder(); public abstract AccessControlContext getContext(SettingControl sc); + + public abstract EventSettings newEventSettings(EventSettingsModifier esm); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java index 2f122fba426..5c01370f1e9 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java @@ -742,6 +742,12 @@ public static void waitFlush(long timeOut) { } + public static Instant epochNanosToInstant(long epochNanos) { + long epochSeconds = epochNanos / 1_000_000_000L; + long nanoAdjustment = epochNanos - 1_000_000_000L * epochSeconds; + return Instant.ofEpochSecond(epochSeconds, nanoAdjustment); + } + public static long timeToNanos(Instant timestamp) { return timestamp.getEpochSecond() * 1_000_000_000L + timestamp.getNano(); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/AbstractEventStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/AbstractEventStream.java index 05558ff3551..3d78b43a218 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/AbstractEventStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/AbstractEventStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, 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 @@ -31,11 +31,16 @@ import java.security.PrivilegedAction; import java.time.Duration; import java.time.Instant; +import java.util.Collections; +import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; +import jdk.jfr.Configuration; +import jdk.jfr.EventType; import jdk.jfr.consumer.EventStream; +import jdk.jfr.consumer.MetadataEvent; import jdk.jfr.consumer.RecordedEvent; import jdk.jfr.internal.LogLevel; import jdk.jfr.internal.LogTag; @@ -47,23 +52,25 @@ * Purpose of this class is to simplify the implementation of * an event stream. */ -abstract class AbstractEventStream implements EventStream { +public abstract class AbstractEventStream implements EventStream { private final static AtomicLong counter = new AtomicLong(); private final Object terminated = new Object(); private final Runnable flushOperation = () -> dispatcher().runFlushActions(); private final AccessControlContext accessControllerContext; - private final StreamConfiguration configuration = new StreamConfiguration(); - private final PlatformRecording recording; + private final StreamConfiguration streamConfiguration = new StreamConfiguration(); + protected final PlatformRecording recording; + private final List configurations; private volatile Thread thread; private Dispatcher dispatcher; private volatile boolean closed; - AbstractEventStream(AccessControlContext acc, PlatformRecording recording) throws IOException { + AbstractEventStream(AccessControlContext acc, PlatformRecording recording, List configurations) throws IOException { this.accessControllerContext = Objects.requireNonNull(acc); this.recording = recording; + this.configurations = configurations; } @Override @@ -76,10 +83,10 @@ abstract class AbstractEventStream implements EventStream { abstract public void close(); protected final Dispatcher dispatcher() { - if (configuration.hasChanged()) { // quick check - synchronized (configuration) { - dispatcher = new Dispatcher(configuration); - configuration.setChanged(false); + if (streamConfiguration.hasChanged()) { // quick check + synchronized (streamConfiguration) { + dispatcher = new Dispatcher(streamConfiguration); + streamConfiguration.setChanged(false); } } return dispatcher; @@ -87,74 +94,74 @@ protected final Dispatcher dispatcher() { @Override public final void setOrdered(boolean ordered) { - configuration.setOrdered(ordered); + streamConfiguration.setOrdered(ordered); } @Override public final void setReuse(boolean reuse) { - configuration.setReuse(reuse); + streamConfiguration.setReuse(reuse); } @Override public final void setStartTime(Instant startTime) { Objects.nonNull(startTime); - synchronized (configuration) { - if (configuration.started) { + synchronized (streamConfiguration) { + if (streamConfiguration.started) { throw new IllegalStateException("Stream is already started"); } if (startTime.isBefore(Instant.EPOCH)) { startTime = Instant.EPOCH; } - configuration.setStartTime(startTime); + streamConfiguration.setStartTime(startTime); } } @Override public final void setEndTime(Instant endTime) { Objects.requireNonNull(endTime); - synchronized (configuration) { - if (configuration.started) { + synchronized (streamConfiguration) { + if (streamConfiguration.started) { throw new IllegalStateException("Stream is already started"); } - configuration.setEndTime(endTime); + streamConfiguration.setEndTime(endTime); } } @Override public final void onEvent(Consumer action) { Objects.requireNonNull(action); - configuration.addEventAction(action); + streamConfiguration.addEventAction(action); } @Override public final void onEvent(String eventName, Consumer action) { Objects.requireNonNull(eventName); Objects.requireNonNull(action); - configuration.addEventAction(eventName, action); + streamConfiguration.addEventAction(eventName, action); } @Override public final void onFlush(Runnable action) { Objects.requireNonNull(action); - configuration.addFlushAction(action); + streamConfiguration.addFlushAction(action); } @Override public final void onClose(Runnable action) { Objects.requireNonNull(action); - configuration.addCloseAction(action); + streamConfiguration.addCloseAction(action); } @Override public final void onError(Consumer action) { Objects.requireNonNull(action); - configuration.addErrorAction(action); + streamConfiguration.addErrorAction(action); } @Override public final boolean remove(Object action) { Objects.requireNonNull(action); - return configuration.remove(action); + return streamConfiguration.remove(action); } @Override @@ -227,14 +234,14 @@ protected final Runnable getFlushOperation() { } private void startInternal(long startNanos) { - synchronized (configuration) { - if (configuration.started) { + synchronized (streamConfiguration) { + if (streamConfiguration.started) { throw new IllegalStateException("Event stream can only be started once"); } - if (recording != null && configuration.startTime == null) { - configuration.setStartNanos(startNanos); + if (recording != null && streamConfiguration.startTime == null) { + streamConfiguration.setStartNanos(startNanos); } - configuration.setStarted(true); + streamConfiguration.setStarted(true); } } @@ -272,4 +279,29 @@ private String nextThreadName() { counter.incrementAndGet(); return "JFR Event Stream " + counter; } + + @Override + public void onMetadata(Consumer action) { + Objects.requireNonNull(action); + synchronized (streamConfiguration) { + if (streamConfiguration.started) { + throw new IllegalStateException("Stream is already started"); + } + } + streamConfiguration.addMetadataAction(action); + } + + protected final void emitMetadataEvent(ChunkParser parser) { + if (parser.hasStaleMetadata()) { + if (dispatcher.hasMetadataHandler()) { + List ce = parser.getEventTypes(); + List pe = parser.getPreviousEventTypes(); + if (ce != pe) { + MetadataEvent me = JdkJfrConsumer.instance().newMetadataEvent(pe, ce, configurations); + dispatcher.runMetadataActions(me); + } + parser.setStaleMetadata(false); + } + } + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java index 203c3e82e83..4027f447cf4 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, 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 @@ -34,15 +34,15 @@ import jdk.jfr.internal.Utils; public final class ChunkHeader { - private static final long HEADER_SIZE = 68; - private static final byte UPDATING_CHUNK_HEADER = (byte) 255; - private static final long CHUNK_SIZE_POSITION = 8; - private static final long DURATION_NANOS_POSITION = 40; - private static final long FILE_STATE_POSITION = 64; - private static final long FLAG_BYTE_POSITION = 67; - private static final long METADATA_TYPE_ID = 0; - private static final byte[] FILE_MAGIC = { 'F', 'L', 'R', '\0' }; - private static final int MASK_FINAL_CHUNK = 1 << 1; + static final long HEADER_SIZE = 68; + static final byte UPDATING_CHUNK_HEADER = (byte) 255; + static final long CHUNK_SIZE_POSITION = 8; + static final long DURATION_NANOS_POSITION = 40; + static final long FILE_STATE_POSITION = 64; + static final long FLAG_BYTE_POSITION = 67; + static final long METADATA_TYPE_ID = 0; + static final byte[] FILE_MAGIC = { 'F', 'L', 'R', '\0' }; + static final int MASK_FINAL_CHUNK = 1 << 1; private final short major; private final short minor; @@ -90,8 +90,8 @@ private ChunkHeader(RecordingInput input, long absoluteChunkStart, long id) thro if (major != 1 && major != 2) { throw new IOException("File version " + major + "." + minor + ". Only Flight Recorder files of version 1.x and 2.x can be read by this JDK."); } - input.readRawLong(); // chunk size - Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Chunk: chunkSize=" + chunkSize); + long c = input.readRawLong(); // chunk size + Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Chunk: chunkSize=" + c); input.readRawLong(); // constant pool position Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Chunk: constantPoolPosition=" + constantPoolPosition); input.readRawLong(); // metadata position @@ -109,7 +109,7 @@ private ChunkHeader(RecordingInput input, long absoluteChunkStart, long id) thro input.position(absoluteEventStart); } - void refresh() throws IOException { + public void refresh() throws IOException { while (true) { byte fileState1; input.positionPhysical(absoluteChunkStart + FILE_STATE_POSITION); @@ -163,6 +163,14 @@ void refresh() throws IOException { } } + public boolean readHeader(byte[] bytes, int count) throws IOException { + input.position(absoluteChunkStart); + for (int i = 0; i< count; i++) { + bytes[i] = input.readPhysicalByte(); + } + return bytes[(int)FILE_STATE_POSITION] != UPDATING_CHUNK_HEADER; + } + public void awaitFinished() throws IOException { if (finished) { return; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java index 9c7806c4a9e..043bac38589 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java @@ -27,6 +27,7 @@ import java.io.IOException; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.StringJoiner; @@ -95,9 +96,8 @@ private boolean is(int flags) { private static final String CHUNKHEADER = "jdk.types.ChunkHeader"; private final RecordingInput input; private final ChunkHeader chunkHeader; - private final MetadataDescriptor metadata; private final TimeConverter timeConverter; - private final MetadataDescriptor previousMetadata; + private final LongMap constantLookups; private LongMap typeMap; @@ -107,6 +107,9 @@ private boolean is(int flags) { private Runnable flushOperation; private ParserConfiguration configuration; private volatile boolean closed; + private MetadataDescriptor previousMetadata; + private MetadataDescriptor metadata; + private boolean staleMetadata = true; public ChunkParser(RecordingInput input) throws IOException { this(input, new ParserConfiguration()); @@ -206,11 +209,13 @@ RecordedEvent readStreamingEvent() throws IOException { // Read metadata and constant pools for the next segment if (chunkHeader.getMetataPosition() != metadataPosition) { Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Found new metadata in chunk. Rebuilding types and parsers"); - MetadataDescriptor metadata = chunkHeader.readMetadata(previousMetadata); + this.previousMetadata = this.metadata; + this.metadata = chunkHeader.readMetadata(previousMetadata); ParserFactory factory = new ParserFactory(metadata, constantLookups, timeConverter); parsers = factory.getParsers(); typeMap = factory.getTypeMap(); updateConfiguration(); + setStaleMetadata(true); } if (constantPosition != chunkHeader.getConstantPoolPosition()) { Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Found new constant pool data. Filling up pools with new values"); @@ -426,6 +431,14 @@ public List getEventTypes() { return metadata.getEventTypes(); } + public List getPreviousEventTypes() { + if (previousMetadata == null) { + return Collections.emptyList(); + } else { + return previousMetadata.getEventTypes(); + } + } + public boolean isLastChunk() throws IOException { return chunkHeader.isLastChunk(); } @@ -456,7 +469,23 @@ public boolean isFinalChunk() { public void close() { this.closed = true; + try { + input.close(); + } catch(IOException e) { + // ignore + } Utils.notifyFlush(); } + public long getEndNanos() { + return getStartNanos() + getChunkDuration(); + } + + public void setStaleMetadata(boolean stale) { + this.staleMetadata = stale; + } + + public boolean hasStaleMetadata() { + return staleMetadata; + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/Dispatcher.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/Dispatcher.java index 4dab2a5b929..ea8b02a2fe8 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/Dispatcher.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/Dispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, 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 @@ -31,12 +31,15 @@ import java.util.function.Consumer; import jdk.jfr.EventType; +import jdk.jfr.consumer.MetadataEvent; import jdk.jfr.consumer.RecordedEvent; import jdk.jfr.internal.LongMap; import jdk.jfr.internal.consumer.ChunkParser.ParserConfiguration; final class Dispatcher { + public final static RecordedEvent FLUSH_MARKER = JdkJfrConsumer.instance().newRecordedEvent(null, null, 0L, 0L); + final static class EventDispatcher { private final static EventDispatcher[] NO_DISPATCHERS = new EventDispatcher[0]; @@ -62,6 +65,7 @@ public Consumer getAction() { } private final Consumer[] errorActions; + private final Consumer[] metadataActions; private final Runnable[] flushActions; private final Runnable[] closeActions; private final EventDispatcher[] dispatchers; @@ -81,25 +85,42 @@ public Dispatcher(StreamConfiguration c) { this.flushActions = c.flushActions.toArray(new Runnable[0]); this.closeActions = c.closeActions.toArray(new Runnable[0]); this.errorActions = c.errorActions.toArray(new Consumer[0]); + this.metadataActions = c.metadataActions.toArray(new Consumer[0]); this.dispatchers = c.eventActions.toArray(new EventDispatcher[0]); this.parserConfiguration = new ParserConfiguration(0, Long.MAX_VALUE, c.reuse, c.ordered, buildFilter(dispatchers)); this.startTime = c.startTime; this.endTime = c.endTime; this.startNanos = c.startNanos; this.endNanos = c.endNanos; + EventDispatcher[] ed = new EventDispatcher[1]; + ed[0] = new EventDispatcher(null, e -> { + runFlushActions(); + }); + dispatcherLookup.put(1L, ed); } - public void runFlushActions() { - Runnable[] flushActions = this.flushActions; - for (int i = 0; i < flushActions.length; i++) { + public void runMetadataActions(MetadataEvent event) { + Consumer[] metadataActions = this.metadataActions; + for (int i = 0; i < metadataActions.length; i++) { try { - flushActions[i].run(); + metadataActions[i].accept(event); } catch (Exception e) { handleError(e); } } } + public void runFlushActions() { + Runnable[] flushActions = this.flushActions; + for (int i = 0; i < flushActions.length; i++) { + try { + flushActions[i].run(); + } catch (Exception e) { + handleError(e); + } + } + } + public void runCloseActions() { Runnable[] closeActions = this.closeActions; for (int i = 0; i < closeActions.length; i++) { @@ -185,4 +206,8 @@ private void handleError(Throwable e) { private void defaultErrorHandler(Throwable e) { e.printStackTrace(); } + + public boolean hasMetadataHandler() { + return metadataActions.length > 0; + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java index 66a01e7d0c6..192dabd8138 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,11 +28,15 @@ import java.io.IOException; import java.nio.file.Path; import java.security.AccessControlContext; +import java.time.Duration; import java.time.Instant; import java.util.Arrays; import java.util.Comparator; +import java.util.List; import java.util.Objects; +import java.util.function.Consumer; +import jdk.jfr.Configuration; import jdk.jfr.consumer.RecordedEvent; import jdk.jfr.internal.JVM; import jdk.jfr.internal.PlatformRecording; @@ -49,18 +53,20 @@ public class EventDirectoryStream extends AbstractEventStream { private final static Comparator EVENT_COMPARATOR = JdkJfrConsumer.instance().eventComparator(); private final RepositoryFiles repositoryFiles; - private final PlatformRecording recording; private final FileAccess fileAccess; private ChunkParser currentParser; private long currentChunkStartNanos; private RecordedEvent[] sortedCache; private int threadExclusionLevel = 0; + protected volatile long maxSize; + protected volatile Duration maxAge; - public EventDirectoryStream(AccessControlContext acc, Path p, FileAccess fileAccess, PlatformRecording recording) throws IOException { - super(acc, recording); + private volatile Consumer onCompleteHandler; + + public EventDirectoryStream(AccessControlContext acc, Path p, FileAccess fileAccess, PlatformRecording recording, List configurations) throws IOException { + super(acc, recording, configurations); this.fileAccess = Objects.requireNonNull(fileAccess); - this.recording = recording; this.repositoryFiles = new RepositoryFiles(fileAccess, p); } @@ -71,6 +77,18 @@ public void close() { repositoryFiles.close(); if (currentParser != null) { currentParser.close(); + onComplete(currentParser.getEndNanos()); + } + } + + public void setChunkCompleteHandler(Consumer handler) { + onCompleteHandler = handler; + } + + private void onComplete(long epochNanos) { + Consumer handler = onCompleteHandler; + if (handler != null) { + handler.accept(epochNanos); } } @@ -110,9 +128,9 @@ protected void processRecursionSafe() throws IOException { Path path; boolean validStartTime = recording != null || disp.startTime != null; if (validStartTime) { - path = repositoryFiles.firstPath(disp.startNanos); + path = repositoryFiles.firstPath(disp.startNanos, true); } else { - path = repositoryFiles.lastPath(); + path = repositoryFiles.lastPath(true); } if (path == null) { // closed return; @@ -122,9 +140,10 @@ protected void processRecursionSafe() throws IOException { currentParser = new ChunkParser(input, disp.parserConfiguration); long segmentStart = currentParser.getStartNanos() + currentParser.getChunkDuration(); long filterStart = validStartTime ? disp.startNanos : segmentStart; - long filterEnd = disp.endTime != null ? disp.endNanos: Long.MAX_VALUE; + long filterEnd = disp.endTime != null ? disp.endNanos : Long.MAX_VALUE; while (!isClosed()) { + emitMetadataEvent(currentParser); while (!isClosed() && !currentParser.isChunkFinished()) { disp = dispatcher(); if (disp != lastDisp) { @@ -159,17 +178,19 @@ protected void processRecursionSafe() throws IOException { return; } long durationNanos = currentParser.getChunkDuration(); + long endChunkNanos = currentParser.getEndNanos(); if (durationNanos == 0) { // Avoid reading the same chunk again and again if // duration is 0 ns durationNanos++; } - path = repositoryFiles.nextPath(currentChunkStartNanos + durationNanos); + path = repositoryFiles.nextPath(currentChunkStartNanos + durationNanos, true); if (path == null) { return; // stream closed } currentChunkStartNanos = repositoryFiles.getTimestamp(path); input.setFile(path); + onComplete(endChunkNanos); currentParser = currentParser.newChunkParser(); // TODO: Optimization. No need filter when we reach new chunk // Could set start = 0; @@ -199,6 +220,7 @@ private void processOrdered(Dispatcher c) throws IOException { } sortedCache[index++] = e; } + emitMetadataEvent(currentParser); // no events found if (index == 0 && currentParser.isChunkFinished()) { return; @@ -217,6 +239,7 @@ private boolean processUnordered(Dispatcher c) throws IOException { while (true) { RecordedEvent e = currentParser.readStreamingEvent(); if (e == null) { + emitMetadataEvent(currentParser); return true; } else { c.dispatch(e); @@ -224,4 +247,11 @@ private boolean processUnordered(Dispatcher c) throws IOException { } } + public void setMaxSize(long maxSize) { + this.maxSize = maxSize; + } + + public void setMaxAge(Duration maxAge) { + this.maxAge = maxAge; + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java index 8df7e5cfa25..6db1d7ae1bf 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java @@ -29,9 +29,9 @@ import java.nio.file.Path; import java.security.AccessControlContext; import java.util.Arrays; +import java.util.Collections; import java.util.Comparator; import java.util.Objects; - import jdk.jfr.consumer.RecordedEvent; /** @@ -47,7 +47,7 @@ public final class EventFileStream extends AbstractEventStream { private RecordedEvent[] cacheSorted; public EventFileStream(AccessControlContext acc, Path path) throws IOException { - super(acc, null); + super(acc, null, Collections.emptyList()); Objects.requireNonNull(path); this.input = new RecordingInput(path.toFile(), FileAccess.UNPRIVILEGED); } @@ -87,6 +87,7 @@ protected void process() throws IOException { currentParser = new ChunkParser(input, disp.parserConfiguration); while (!isClosed()) { + emitMetadataEvent(currentParser); if (currentParser.getStartNanos() > end) { close(); return; @@ -116,11 +117,16 @@ private void processOrdered(Dispatcher c) throws IOException { int index = 0; while (true) { event = currentParser.readEvent(); + if (event == Dispatcher.FLUSH_MARKER) { + emitMetadataEvent(currentParser); + dispatchOrdered(c, index); + index = 0; + continue; + } + if (event == null) { - Arrays.sort(cacheSorted, 0, index, EVENT_COMPARATOR); - for (int i = 0; i < index; i++) { - c.dispatch(cacheSorted[i]); - } + emitMetadataEvent(currentParser); + dispatchOrdered(c, index); return; } if (index == cacheSorted.length) { @@ -132,13 +138,23 @@ private void processOrdered(Dispatcher c) throws IOException { } } + private void dispatchOrdered(Dispatcher c, int index) { + Arrays.sort(cacheSorted, 0, index, EVENT_COMPARATOR); + for (int i = 0; i < index; i++) { + c.dispatch(cacheSorted[i]); + } + } + private void processUnordered(Dispatcher c) throws IOException { while (!isClosed()) { RecordedEvent event = currentParser.readEvent(); if (event == null) { + emitMetadataEvent(currentParser); return; } - c.dispatch(event); + if (event != Dispatcher.FLUSH_MARKER) { + c.dispatch(event); + } } } } diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/Stream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/FinishedStream.java similarity index 76% rename from src/jdk.management.jfr/share/classes/jdk/management/jfr/Stream.java rename to src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/FinishedStream.java index 29df664e8d6..b4ee13614c1 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/Stream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/FinishedStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,37 +22,25 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - -package jdk.management.jfr; +package jdk.jfr.internal.consumer; import java.io.BufferedInputStream; -import java.io.Closeable; import java.io.IOException; import java.io.InputStream; -final class Stream implements Closeable { +import jdk.jfr.internal.management.EventByteStream; - private final long identifier; +public final class FinishedStream extends EventByteStream { private final BufferedInputStream inputStream; private final byte[] buffer; - private volatile long time; - - Stream(InputStream is, long identifier, int blockSize) { + public FinishedStream(InputStream is, int blockSize) { + super(); this.inputStream = new BufferedInputStream(is, 50000); - this.identifier = identifier; this.buffer = new byte[blockSize]; } - private void touch() { - time = System.currentTimeMillis(); - } - - public long getLastTouched() { - return time; - } - - public byte[] read() throws IOException { + public synchronized byte[] read() throws IOException { // OK to reuse buffer since this // is only used for serialization touch(); @@ -71,11 +59,8 @@ public byte[] read() throws IOException { } @Override - public void close() throws IOException { + public synchronized void close() throws IOException { inputStream.close(); } - public long getId() { - return identifier; - } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/JdkJfrConsumer.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/JdkJfrConsumer.java index edd2d755a5d..086579b8d2a 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/JdkJfrConsumer.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/JdkJfrConsumer.java @@ -28,7 +28,12 @@ import java.io.IOException; import java.util.Comparator; import java.util.List; +import java.util.function.Consumer; +import jdk.jfr.Configuration; +import jdk.jfr.EventType; +import jdk.jfr.consumer.EventStream; +import jdk.jfr.consumer.MetadataEvent; import jdk.jfr.consumer.RecordedClass; import jdk.jfr.consumer.RecordedClassLoader; import jdk.jfr.consumer.RecordedEvent; @@ -40,6 +45,7 @@ import jdk.jfr.consumer.RecordedThreadGroup; import jdk.jfr.consumer.RecordingFile; import jdk.jfr.internal.Type; + /* * Purpose of this class is to give package private access to * the jdk.jfr.consumer package @@ -98,4 +104,7 @@ public static JdkJfrConsumer instance() { public abstract void setEndTicks(RecordedEvent event, long endTicks); public abstract Object[] eventValues(RecordedEvent event); + + public abstract MetadataEvent newMetadataEvent(List previous, List current, List configuration); + } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/OngoingStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/OngoingStream.java new file mode 100644 index 00000000000..a462bde64da --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/OngoingStream.java @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jfr.internal.consumer; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.file.Path; +import java.time.Instant; + +import jdk.jfr.Recording; +import jdk.jfr.RecordingState; +import jdk.jfr.internal.Utils; +import jdk.jfr.internal.SecuritySupport; +import jdk.jfr.internal.SecuritySupport.SafePath; +import jdk.jfr.internal.management.EventByteStream; +import jdk.jfr.internal.management.ManagementSupport; + +public final class OngoingStream extends EventByteStream { + + private static final byte[] EMPTY_ARRAY = new byte[0]; + private static final int HEADER_SIZE = (int)ChunkHeader.HEADER_SIZE; + private static final int HEADER_FILE_STATE_POSITION = (int)ChunkHeader.FILE_STATE_POSITION; + private static final byte MODIFYING_STATE = ChunkHeader.UPDATING_CHUNK_HEADER; + + private final RepositoryFiles repositoryFiles; + private final Recording recording; + private final int blockSize; + private final long endTimeNanos; + private final byte[] headerBytes = new byte[HEADER_SIZE]; + + private RecordingInput input; + private ChunkHeader header; + private long position; + private long startTimeNanos; + private Path path; + private boolean first = true; + + public OngoingStream(Recording recording, int blockSize, long startTimeNanos, long endTimeNanos) { + super(); + this.recording = recording; + this.blockSize = blockSize; + this.startTimeNanos = startTimeNanos; + this.endTimeNanos = endTimeNanos; + this.repositoryFiles = new RepositoryFiles(SecuritySupport.PRIVILEGED, null); + } + + public synchronized byte[] read() throws IOException { + try { + return readBytes(); + } catch (IOException ioe) { + if (recording.getState() == RecordingState.CLOSED) { + // Recording closed, return null; + return null; + } + // Something unexpected has happened. + throw ioe; + } + } + + private byte[] readBytes() throws IOException { + touch(); + if (recording.getState() == RecordingState.NEW) { + return EMPTY_ARRAY; + } + + if (recording.getState() == RecordingState.DELAYED) { + return EMPTY_ARRAY; + } + + if (first) { + // In case stream starts before recording + long s = ManagementSupport.getStartTimeNanos(recording); + startTimeNanos = Math.max(s, startTimeNanos); + first = false; + } + + while (true) { + if (startTimeNanos > endTimeNanos) { + return null; + } + if (isRecordingClosed()) { + closeInput(); + return null; + } + if (!ensurePath()) { + return EMPTY_ARRAY; + } + if (!ensureInput()) { + return EMPTY_ARRAY; + } + if (position < header.getChunkSize()) { + long size = Math.min(header.getChunkSize() - position, blockSize); + return readBytes((int) size); + } + if (header.isFinished()) { + if (header.getDurationNanos() < 1) { + throw new IOException("No progress"); + } + startTimeNanos += header.getDurationNanos(); + Instant timestamp = Utils.epochNanosToInstant(startTimeNanos); + ManagementSupport.removeBefore(recording, timestamp); + closeInput(); + } else { + header.refresh(); + if (position >= header.getChunkSize()) { + return EMPTY_ARRAY; + } + } + } + } + + private boolean isRecordingClosed() { + return recording != null && recording.getState() == RecordingState.CLOSED; + } + + private void closeInput() { + if (input != null) { + try { + input.close(); + } catch (IOException ioe) { + // ignore + } + input = null; + position = 0; + path = null; + } + } + + private byte[] readBytes(int size) throws IOException { + if (position == 0) { + return readWithHeader(size); + } else { + return readNonHeader(size); + } + } + + private byte[] readNonHeader(int size) throws IOException { + byte[] result = new byte[size]; + input.readFully(result); + position += size; + return result; + } + + private byte[] readWithHeader(int size) throws IOException { + byte[] bytes = new byte[Math.max(HEADER_SIZE, size)]; + for (int attempts = 0; attempts < 25; attempts++) { + // read twice and check files state to avoid simultaneous change by JVM + input.position(0); + input.readFully(bytes, 0, HEADER_SIZE); + input.position(0); + input.readFully(headerBytes); + if (bytes[HEADER_FILE_STATE_POSITION] != MODIFYING_STATE) { + if (bytes[HEADER_FILE_STATE_POSITION] == headerBytes[HEADER_FILE_STATE_POSITION]) { + ByteBuffer buffer = ByteBuffer.wrap(bytes); + // 0-3: magic + // 4-5: major + // 6-7: minor + // 8-15: chunk size + buffer.putLong(8, HEADER_SIZE); + // 16-23: constant pool offset + buffer.putLong(16, 0); + // 24-31: metadata offset + buffer.putLong(24, 0); + // 32-39: chunk start nanos + // 40-47 duration + buffer.putLong(40, 0); + // 48-55: chunk start ticks + // 56-63: ticks per second + // 64: file state + buffer.put(64, (byte) 1); + // 65-67: extension bit + int left = bytes.length - HEADER_SIZE; + input.readFully(bytes, HEADER_SIZE, left); + position += bytes.length; + return bytes; + } + } + takeNap(); + } + return EMPTY_ARRAY; + } + + private void takeNap() throws IOException { + try { + Thread.sleep(10); + } catch (InterruptedException ie) { + throw new IOException("Read operation interrupted", ie); + } + } + + private boolean ensureInput() throws IOException { + if (input == null) { + if (SecuritySupport.getFileSize(new SafePath(path)) < HEADER_SIZE) { + return false; + } + input = new RecordingInput(path.toFile(), SecuritySupport.PRIVILEGED); + header = new ChunkHeader(input); + } + return true; + } + + private boolean ensurePath() { + if (path == null) { + path = repositoryFiles.nextPath(startTimeNanos, false); + } + return path != null; + } + + @Override + public synchronized void close() throws IOException { + closeInput(); + // Close recording if stream times out. + if (recording.getName().startsWith(EventByteStream.NAME)) { + recording.close(); + } + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java index 23700fd8ed3..e5ba2f4cb29 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, 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 @@ -218,7 +218,10 @@ long size() { @Override public void close() throws IOException { - file.close(); + RandomAccessFile ra = file; + if (ra != null) { + ra.close(); + } } @Override @@ -426,13 +429,5 @@ public void setFile(Path path) throws IOException { file = null; initialize(path.toFile()); } -/* - - - - - * - * - */ } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RepositoryFiles.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RepositoryFiles.java index 12810c42c44..754e5fd6d3d 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RepositoryFiles.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RepositoryFiles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, 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 @@ -61,7 +61,7 @@ public static void notifyNewFile() { private volatile boolean closed; - RepositoryFiles(FileAccess fileAccess, Path repository) { + public RepositoryFiles(FileAccess fileAccess, Path repository) { this.repository = repository; this.fileAccess = fileAccess; this.waitObject = repository == null ? WAIT_OBJECT : new Object(); @@ -71,26 +71,27 @@ long getTimestamp(Path p) { return pathLookup.get(p); } - Path lastPath() { - if (waitForPaths()) { + public Path lastPath(boolean wait) { + if (updatePaths(wait)) { return pathSet.lastEntry().getValue(); } return null; // closed } - Path firstPath(long startTimeNanos) { - if (waitForPaths()) { + public Path firstPath(long startTimeNanos, boolean wait) { + if (updatePaths(wait)) { // Pick closest chunk before timestamp Long time = pathSet.floorKey(startTimeNanos); if (time != null) { startTimeNanos = time; } - return path(startTimeNanos); + return path(startTimeNanos, wait); } return null; // closed } - private boolean waitForPaths() { + private boolean updatePaths(boolean wait) { + int beforeSize = pathLookup.size(); while (!closed) { try { if (updatePaths()) { @@ -103,12 +104,16 @@ private boolean waitForPaths() { // was accessed, or if new file has been written yet // Just ignore, and retry later. } - nap(); + if (wait) { + nap(); + } else { + return pathLookup.size() > beforeSize; + } } return !closed; } - Path nextPath(long startTimeNanos) { + public Path nextPath(long startTimeNanos, boolean wait) { if (closed) { return null; } @@ -127,10 +132,10 @@ Path nextPath(long startTimeNanos) { // ignore } // try to get the next file - return path(startTimeNanos); + return path(startTimeNanos, wait); } - private Path path(long timestamp) { + private Path path(long timestamp, boolean wait) { if (closed) { return null; } @@ -143,7 +148,7 @@ private Path path(long timestamp) { } return path; } - if (!waitForPaths()) { + if (!updatePaths(wait)) { return null; // closed } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/StreamConfiguration.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/StreamConfiguration.java index 9fd47bfdf66..b86fbd1c09e 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/StreamConfiguration.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/StreamConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, 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 @@ -30,6 +30,7 @@ import java.util.List; import java.util.function.Consumer; +import jdk.jfr.consumer.MetadataEvent; import jdk.jfr.consumer.RecordedEvent; import jdk.jfr.internal.Utils; import jdk.jfr.internal.consumer.Dispatcher.EventDispatcher; @@ -39,6 +40,7 @@ final class StreamConfiguration { final List flushActions = new ArrayList<>(); final List eventActions = new ArrayList<>(); final List> errorActions = new ArrayList<>(); + final List> metadataActions = new ArrayList<>(); boolean reuse = true; boolean ordered = true; @@ -56,6 +58,7 @@ public synchronized boolean remove(Object action) { removed |= closeActions.removeIf(e -> e == action); removed |= errorActions.removeIf(e -> e == action); removed |= eventActions.removeIf(e -> e.getAction() == action); + removed |= metadataActions.removeIf(e -> e == action); if (removed) { changed = true; } @@ -86,6 +89,11 @@ public synchronized void addErrorAction(Consumer action) { changed = true; } + public synchronized void addMetadataAction(Consumer action) { + metadataActions.add(action); + changed = true; + } + public synchronized void setReuse(boolean reuse) { this.reuse = reuse; changed = true; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/management/EventByteStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/EventByteStream.java new file mode 100644 index 00000000000..a6f75b22f2c --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/EventByteStream.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jfr.internal.management; + +import java.io.Closeable; + +import java.io.IOException; +import java.io.InputStream; +import java.util.concurrent.atomic.AtomicLong; + +import jdk.jfr.Recording; +import jdk.jfr.internal.consumer.FinishedStream; +import jdk.jfr.internal.consumer.OngoingStream; + +// abstract class that hides if a recording is ongoing or finished. +public abstract class EventByteStream implements Closeable { + public static final String NAME = "Remote Recording Stream"; + private static AtomicLong idCounter = new AtomicLong(); + + private final long identifier; + private volatile long time; + + public EventByteStream() { + this.identifier = idCounter.incrementAndGet(); + } + + public static EventByteStream newOngoingStream(Recording recording, int blockSize, long startTimeNanos,long endTimeNanos) { + return new OngoingStream(recording, blockSize, startTimeNanos, endTimeNanos); + } + + public static EventByteStream newFinishedStream(InputStream is, int blockSize) { + return new FinishedStream(is, blockSize); + } + + final protected void touch() { + time = System.currentTimeMillis(); + } + + final public long getLastTouched() { + return time; + } + + abstract public byte[] read() throws IOException; + + final public long getId() { + return identifier; + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/management/EventSettingsModifier.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/EventSettingsModifier.java new file mode 100644 index 00000000000..4d70bcfe651 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/EventSettingsModifier.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jfr.internal.management; + +import java.util.Map; + +/** + * Purpose of the interface is to be able to provide an implementation of + * EventSettings in the jdk.management.jfr module. + * + */ +public interface EventSettingsModifier { + + void with(String name, String value); + + Map toMap(); + +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java index 32a3f7a393a..6505364dd93 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,14 +26,22 @@ package jdk.jfr.internal.management; import java.io.IOException; +import java.nio.file.Path; import java.nio.file.Paths; import java.time.Duration; +import java.time.Instant; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.security.AccessControlContext; +import jdk.jfr.Configuration; +import jdk.jfr.EventSettings; import jdk.jfr.EventType; import jdk.jfr.Recording; +import jdk.jfr.consumer.EventStream; import jdk.jfr.internal.JVMSupport; import jdk.jfr.internal.LogLevel; import jdk.jfr.internal.LogTag; @@ -43,6 +51,9 @@ import jdk.jfr.internal.PrivateAccess; import jdk.jfr.internal.Utils; import jdk.jfr.internal.WriteableUserPath; +import jdk.jfr.internal.consumer.EventDirectoryStream; +import jdk.jfr.internal.consumer.FileAccess; +import jdk.jfr.internal.consumer.JdkJfrConsumer; import jdk.jfr.internal.instrument.JDKEvents; /** @@ -83,6 +94,11 @@ public static long parseTimespan(String s) { return Utils.parseTimespan(s); } + // Reuse internal code for converting nanoseconds since epoch to Instant + public static Instant epochNanosToInstant(long epochNanos) { + return Utils.epochNanosToInstant(epochNanos); + } + // Reuse internal code for formatting settings public static final String formatTimespan(Duration dValue, String separation) { return Utils.formatTimespan(dValue, separation); @@ -93,6 +109,11 @@ public static void logError(String message) { Logger.log(LogTag.JFR, LogLevel.ERROR, message); } + // Reuse internal logging mechanism + public static void logDebug(String message) { + Logger.log(LogTag.JFR, LogLevel.DEBUG, message); + } + // Get the textual representation when the destination was set, which // requires access to jdk.jfr.internal.PlatformRecording public static String getDestinationOriginalText(Recording recording) { @@ -101,6 +122,8 @@ public static String getDestinationOriginalText(Recording recording) { return wup == null ? null : wup.getOriginalText(); } + // Needed to check if destination can be set, so FlightRecorderMXBean::setRecordingOption + // can abort if not all data is valid public static void checkSetDestination(Recording recording, String destination) throws IOException{ PlatformRecording pr = PrivateAccess.getInstance().getPlatformRecording(recording); if(destination != null){ @@ -108,4 +131,45 @@ public static void checkSetDestination(Recording recording, String destination) pr.checkSetDestination(wup); } } + + // Needed to modify setting using fluent API. + public static EventSettings newEventSettings(EventSettingsModifier esm) { + return PrivateAccess.getInstance().newEventSettings(esm); + } + + // When streaming an ongoing recording, consumed chunks should be removed + public static void removeBefore(Recording recording, Instant timestamp) { + PlatformRecording pr = PrivateAccess.getInstance().getPlatformRecording(recording); + pr.removeBefore(timestamp); + + } + + // Needed callback to detect when a chunk has been parsed. + public static void setOnChunkCompleteHandler(EventStream stream, Consumer consumer) { + EventDirectoryStream eds = (EventDirectoryStream) stream; + eds.setChunkCompleteHandler(consumer); + } + + // Needed to start an ongoing stream at the right chunk, which + // can be identified by the start time with nanosecond precision. + public static long getStartTimeNanos(Recording recording) { + PlatformRecording pr = PrivateAccess.getInstance().getPlatformRecording(recording); + return pr.getStartNanos(); + } + + // Needed to produce Configuration objects for MetadataEvent + public static Configuration newConfiguration(String name, String label, String description, String provider, + Map settings, String contents) { + return PrivateAccess.getInstance().newConfiguration(name, label, description, provider, settings, contents); + } + + // Can't use EventStream.openRepository(...) because + // EventStream::onMetadataData need to supply MetadataEvent + // with configuration objects + public static EventStream newEventDirectoryStream( + AccessControlContext acc, + Path directory, + List confs) throws IOException { + return new EventDirectoryStream(acc, directory, FileAccess.UNPRIVILEGED, null, confs); + } } diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/StreamCleanupTask.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/StreamCleanupTask.java similarity index 87% rename from src/jdk.management.jfr/share/classes/jdk/management/jfr/StreamCleanupTask.java rename to src/jdk.jfr/share/classes/jdk/jfr/internal/management/StreamCleanupTask.java index fe89e3c7bb0..22d14babccc 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/StreamCleanupTask.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/StreamCleanupTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, 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 @@ -23,16 +23,17 @@ * questions. */ -package jdk.management.jfr; +package jdk.jfr.internal.management; import java.util.TimerTask; +// Helper class to StreamManager final class StreamCleanupTask extends TimerTask { - private final Stream stream; + private final EventByteStream stream; private final StreamManager manager; - StreamCleanupTask(StreamManager streamManager, Stream stream) { + StreamCleanupTask(StreamManager streamManager, EventByteStream stream) { this.stream = stream; this.manager = streamManager; } diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/StreamManager.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/StreamManager.java similarity index 56% rename from src/jdk.management.jfr/share/classes/jdk/management/jfr/StreamManager.java rename to src/jdk.jfr/share/classes/jdk/jfr/internal/management/StreamManager.java index b2cf93a2e2b..005bd2932b5 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/StreamManager.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/StreamManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, 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 @@ -23,44 +23,64 @@ * questions. */ -package jdk.management.jfr; +package jdk.jfr.internal.management; import java.io.IOException; import java.io.InputStream; +import java.time.Instant; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Timer; import java.util.concurrent.TimeUnit; -final class StreamManager { +import jdk.jfr.Recording; +import jdk.jfr.internal.consumer.FinishedStream; +import jdk.jfr.internal.consumer.OngoingStream; - public static final long TIME_OUT = TimeUnit.MINUTES.toMillis(2); - public static final int DEFAULT_BLOCK_SIZE = 50000; +// Exposes EventByteStreams to the FlightRecorderMXBean +public final class StreamManager { - private static long idCounter = 0; + public static final long TIME_OUT = TimeUnit.MINUTES.toMillis(200); + public static final int DEFAULT_BLOCK_SIZE = 50000; - private final Map streams = new HashMap<>(); + private final Map streams = new HashMap<>(); private Timer timer; - public synchronized Stream getStream(long streamIdentifer) { - Stream stream = streams.get(streamIdentifer); + public synchronized EventByteStream getStream(long streamIdentifer) { + EventByteStream stream = streams.get(streamIdentifer); if (stream == null) { throw new IllegalArgumentException("Unknown stream identifier " + streamIdentifer); } return stream; } - public synchronized Stream create(InputStream is, int blockSize) { - idCounter++; - Stream stream = new Stream(is, idCounter, blockSize); + public synchronized EventByteStream createOngoing(Recording recording, int blockSize, Instant startTime, Instant endTime) { + long startTimeNanos = 0; + long endTimeNanos = Long.MAX_VALUE; + if (!startTime.equals(Instant.MIN)) { + startTimeNanos = startTime.getEpochSecond() * 1_000_000_000L; + startTimeNanos += startTime.getNano(); + } + if (!endTime.equals(Instant.MAX)) { + endTimeNanos = endTime.getEpochSecond() * 1_000_000_000L; + endTimeNanos+= endTime.getNano(); + } + EventByteStream stream = EventByteStream.newOngoingStream(recording, blockSize, startTimeNanos, endTimeNanos); + streams.put(stream.getId(), stream); + scheduleAbort(stream, System.currentTimeMillis() + TIME_OUT); + return stream; + } + + public synchronized EventByteStream create(InputStream is, int blockSize) { + EventByteStream stream = EventByteStream.newFinishedStream(is, blockSize); streams.put(stream.getId(), stream); scheduleAbort(stream, System.currentTimeMillis() + TIME_OUT); return stream; } - public synchronized void destroy(Stream stream) { + public synchronized void destroy(EventByteStream stream) { try { stream.close(); } catch (IOException e) { @@ -73,7 +93,7 @@ public synchronized void destroy(Stream stream) { } } - public synchronized void scheduleAbort(Stream s, long when) { + public synchronized void scheduleAbort(EventByteStream s, long when) { if (timer == null) { timer = new Timer(true); } diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/DiskRepository.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/DiskRepository.java new file mode 100644 index 00000000000..0bf2a145b23 --- /dev/null +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/DiskRepository.java @@ -0,0 +1,482 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.management.jfr; + +import java.io.Closeable; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Iterator; +import java.util.Objects; + +import jdk.jfr.internal.management.ManagementSupport; + +final class DiskRepository implements Closeable { + + final static class DiskChunk { + final Path path; + final Instant startTime; + Instant endTime; + long size; + + DiskChunk(Path path, long startNanos) { + this.path = path; + this.startTime = ManagementSupport.epochNanosToInstant(startNanos); + } + } + + enum State { + HEADER, EVENT_SIZE, EVENT_TYPE, CHECKPOINT_EVENT_TIMESTAMP, CHECKPOINT_EVENT_DURATION, CHECKPOINT_EVENT_DELTA, + CHECKPOINT_EVENT_FLUSH_TYPE, CHECKPOINT_EVENT_POOL_COUNT, CHECKPOINT_EVENT_HEADER_TYPE, + CHECKPOINT_EVENT_HEADER_ITEM_COUNT, CHECKPOINT_EVENT_HEADER_KEY, CHECKPOINT_EVENT_HEADER_BYTE_ARRAY_LENGTH, + CHECKPOINT_EVENT_HEADER_BYTE_ARRAY_CONTENT, EVENT_PAYLOAD; + + public State next() { + return State.values()[ordinal() + 1]; + } + } + + static final byte CHECKPOINT_WITH_HEADER = (byte) 2; + static final byte MODIFYING_STATE = (byte) 255; + static final byte COMPLETE_STATE = (byte) 0; + static final int HEADER_FILE_STATE_POSITION = 64; + static final int HEADER_START_NANOS_POSITION = 32; + static final int HEADER_SIZE = 68; + static final int HEADER_FILE_DURATION = 40; + + private final Deque activeChunks = new ArrayDeque<>(); + private final Deque deadChunks = new ArrayDeque<>(); + private final boolean deleteDirectory; + private final ByteBuffer buffer = ByteBuffer.allocate(256); + private final Path directory; + + private RandomAccessFile raf; + private RandomAccessFile previousRAF; + private byte previousRAFstate; + private int index; + private int bufferIndex; + private State state = State.HEADER; + private byte[] currentByteArray; + private int typeId; + private int typeIdshift; + private int sizeShift; + private int payLoadSize; + private int longValueshift; + private int eventFieldSize; + private int lastFlush; + private DiskChunk currentChunk; + private Duration maxAge; + private long maxSize; + private long size; + + public DiskRepository(Path path, boolean deleteDirectory) throws IOException { + this.directory = path; + this.deleteDirectory = deleteDirectory; + } + + public synchronized void write(byte[] bytes) throws IOException { + index = 0; + lastFlush = 0; + currentByteArray = bytes; + while (index < bytes.length) { + switch (state) { + case HEADER: + processInitialHeader(); + break; + case EVENT_SIZE: + processEventSize(); + break; + case EVENT_TYPE: + processEventTypeId(); + break; + case CHECKPOINT_EVENT_TIMESTAMP: + case CHECKPOINT_EVENT_DURATION: + case CHECKPOINT_EVENT_DELTA: + case CHECKPOINT_EVENT_POOL_COUNT: + case CHECKPOINT_EVENT_HEADER_TYPE: + case CHECKPOINT_EVENT_HEADER_ITEM_COUNT: + case CHECKPOINT_EVENT_HEADER_KEY: + case CHECKPOINT_EVENT_HEADER_BYTE_ARRAY_LENGTH: + processNumericValueInEvent(); + bufferIndex = 0; + break; + case CHECKPOINT_EVENT_HEADER_BYTE_ARRAY_CONTENT: + processCheckPointHeader(); + break; + case CHECKPOINT_EVENT_FLUSH_TYPE: + processFlush(); + break; + case EVENT_PAYLOAD: + processEvent(); + break; + default: + break; + } + } + // Don't write before header/file is complete + if (raf == null) { + return; + } + flush(); + } + + private void processFlush() throws IOException { + byte b = nextByte(true); + if ((b & CHECKPOINT_WITH_HEADER) != 0) { + state = State.CHECKPOINT_EVENT_POOL_COUNT; + } else { + state = State.EVENT_PAYLOAD; + } + } + + private void processNumericValueInEvent() { + int b = nextByte(true); + // longValue += (((long) (b & 0x7FL)) << longValueshift); + if (b >= 0 || longValueshift == 56) { + state = state.next(); + // longValue = 0; + longValueshift = 0; + } else { + longValueshift += 7; + } + } + + private void processEvent() { + int left = currentByteArray.length - index; + if (left >= payLoadSize) { + index += payLoadSize; + payLoadSize = 0; + state = State.EVENT_SIZE; + } else { + index += left; + payLoadSize -= left; + } + } + + private void processEventTypeId() { + byte b = nextByte(true); + long v = (b & 0x7FL); + typeId += (v << typeIdshift); + if (b >= 0) { + if (typeId == 1) { + state = State.CHECKPOINT_EVENT_TIMESTAMP; + } else { + state = State.EVENT_PAYLOAD; + } + typeIdshift = 0; + typeId = 0; + } else { + typeIdshift += 7; + } + } + + private void processEventSize() throws IOException { + // End of chunk + if (previousRAF != null) { + flush(); + state = State.HEADER; + return; + } + + eventFieldSize++; + byte b = nextByte(false); + long v = (b & 0x7FL); + payLoadSize += (v << sizeShift); + if (b >= 0) { + if (payLoadSize == 0) { + throw new IOException("Event size can't be null." + index); + } + state = State.EVENT_TYPE; + sizeShift = 0; + payLoadSize -= eventFieldSize; + eventFieldSize = 0; + } else { + sizeShift += 7; + } + } + + private void processInitialHeader() throws IOException { + buffer.put(bufferIndex, nextByte(false)); + if (bufferIndex == HEADER_SIZE) { + writeInitialHeader(); + state = State.EVENT_SIZE; + bufferIndex = 0; + if (index != lastFlush + HEADER_SIZE) { + throw new IOException("Expected data before header to be flushed"); + } + lastFlush = index; + } + } + + private void processCheckPointHeader() throws IOException { + buffer.put(bufferIndex, nextByte(true)); + if (bufferIndex == HEADER_SIZE) { + writeCheckPointHeader(); + state = State.EVENT_PAYLOAD; + bufferIndex = 0; + } + } + + private void writeInitialHeader() throws IOException { + DiskChunk previous = currentChunk; + currentChunk = nextChunk(); + raf = new RandomAccessFile(currentChunk.path.toFile(), "rw"); + byte fileState = buffer.get(HEADER_FILE_STATE_POSITION); + buffer.put(HEADER_FILE_STATE_POSITION, MODIFYING_STATE); + raf.write(buffer.array(), 0, HEADER_SIZE); + // Complete previous chunk + completePrevious(previous); + + raf.seek(HEADER_FILE_STATE_POSITION); + raf.writeByte(fileState); + raf.seek(HEADER_SIZE); + } + + private void completePrevious(DiskChunk previous) throws IOException { + if (previousRAF != null) { + previousRAF.seek(HEADER_FILE_STATE_POSITION); + previousRAF.writeByte(previousRAFstate); + previousRAF.close(); + addChunk(previous); + previousRAF = null; + previousRAFstate = (byte) 0; + } + } + + private void writeCheckPointHeader() throws IOException { + Objects.requireNonNull(raf); + byte state = buffer.get(HEADER_FILE_STATE_POSITION); + boolean complete = state == COMPLETE_STATE; + buffer.put(HEADER_FILE_STATE_POSITION, MODIFYING_STATE); + flush(); + long position = raf.getFilePointer(); + raf.seek(HEADER_FILE_STATE_POSITION); + raf.writeByte(MODIFYING_STATE); + raf.seek(0); + raf.write(buffer.array(), 0, HEADER_SIZE); + if (!complete) { + raf.seek(HEADER_FILE_STATE_POSITION); + raf.writeByte(state); + } else { + // will set state to complete when + // header of next file is created. + previousRAF = raf; + previousRAFstate = state; + currentChunk.size = Files.size(currentChunk.path); + long durationNanos = buffer.getLong(HEADER_FILE_DURATION); + Duration d = Duration.ofNanos(durationNanos); + currentChunk.endTime = currentChunk.startTime.plus(d); + } + raf.seek(position); + } + + private void flush() throws IOException { + int length = index - lastFlush; + if (length != 0) { + raf.write(currentByteArray, lastFlush, length); + lastFlush = index; + } + } + + private byte nextByte(boolean inEvent) { + byte b = currentByteArray[index]; + index++; + bufferIndex++; + if (inEvent) { + payLoadSize--; + } + return b; + } + + private DiskChunk nextChunk() throws IOException { + long nanos = buffer.getLong(HEADER_START_NANOS_POSITION); + long epochSecond = nanos / 1_000_000_000; + int nanoOfSecond = (int) (nanos % 1_000_000_000); + ZoneOffset z = OffsetDateTime.now().getOffset(); + LocalDateTime d = LocalDateTime.ofEpochSecond(epochSecond, nanoOfSecond, z); + String filename = formatDateTime(d); + Path p1 = directory.resolve(filename + ".jfr"); + if (!Files.exists(p1)) { + return new DiskChunk(p1, nanos); + } + for (int i = 1; i < 100; i++) { + String s = Integer.toString(i); + if (i < 10) { + s = "0" + s; + } + Path p2 = directory.resolve(filename + "_" + s + ".jfr"); + if (!Files.exists(p2)) { + return new DiskChunk(p2, nanos); + } + } + throw new IOException("Could not create chunk for path " + p1); + } + + static String formatDateTime(LocalDateTime time) { + StringBuilder sb = new StringBuilder(19); + sb.append(time.getYear() / 100); + appendPadded(sb, time.getYear() % 100, true); + appendPadded(sb, time.getMonth().getValue(), true); + appendPadded(sb, time.getDayOfMonth(), true); + appendPadded(sb, time.getHour(), true); + appendPadded(sb, time.getMinute(), true); + appendPadded(sb, time.getSecond(), false); + return sb.toString(); + } + + private static void appendPadded(StringBuilder text, int number, boolean separator) { + if (number < 10) { + text.append('0'); + } + text.append(number); + if (separator) { + text.append('_'); + } + } + + @Override + public synchronized void close() throws IOException { + completePrevious(currentChunk); + if (raf != null) { + raf.close(); + } + deadChunks.addAll(activeChunks); + if (currentChunk != null) { + deadChunks.add(currentChunk); + } + cleanUpDeadChunk(Integer.MAX_VALUE); + if (deleteDirectory) { + try { + Files.delete(directory); + } catch (IOException ioe) { + ManagementSupport.logDebug("Could not delete temp stream repository: " + ioe.getMessage()); + } + } + } + + public synchronized void setMaxAge(Duration maxAge) { + this.maxAge = maxAge; + trimToAge(Instant.now().minus(maxAge)); + } + + public synchronized void setMaxSize(long maxSize) { + this.maxSize = maxSize; + trimToSize(); + } + + private void trimToSize() { + if (maxSize == 0) { + return; + } + int count = 0; + while (size > maxSize && activeChunks.size() > 1) { + removeOldestChunk(); + count++; + } + cleanUpDeadChunk(count + 10); + } + + private void trimToAge(Instant oldest) { + if (maxAge == null) { + return; + } + int count = 0; + while (activeChunks.size() > 1) { + DiskChunk oldestChunk = activeChunks.getLast(); + if (oldestChunk.endTime.isAfter(oldest)) { + return; + } + removeOldestChunk(); + count++; + } + cleanUpDeadChunk(count + 10); + } + + public synchronized void onChunkComplete(Instant timestamp) { + int count = 0; + while (!activeChunks.isEmpty()) { + DiskChunk oldestChunk = activeChunks.peek(); + if (oldestChunk.startTime.isBefore(timestamp)) { + removeOldestChunk(); + count++; + } else { + break; + } + } + cleanUpDeadChunk(count + 10); + } + + private void addChunk(DiskChunk chunk) { + if (maxAge != null) { + trimToAge(chunk.endTime.minus(maxAge)); + } + activeChunks.push(chunk); + size += chunk.size; + trimToSize(); + } + + private void removeOldestChunk() { + DiskChunk chunk = activeChunks.poll(); + deadChunks.add(chunk); + size -= chunk.size; + } + + private void cleanUpDeadChunk(int maxCount) { + int count = 0; + Iterator iterator = deadChunks.iterator(); + while (iterator.hasNext()) { + DiskChunk chunk = iterator.next(); + try { + Files.delete(chunk.path); + iterator.remove(); + } catch (IOException e) { + // ignore + } + count++; + if (count == maxCount) { + return; + } + } + } + + public synchronized void complete() { + if (currentChunk != null) { + try { + completePrevious(currentChunk); + } catch (IOException ioe) { + ManagementSupport.logDebug("Could not complete chunk " + currentChunk.path + " : " + ioe.getMessage()); + } + } + } +} diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/DownLoadThread.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/DownLoadThread.java new file mode 100644 index 00000000000..68d2fc5f6c8 --- /dev/null +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/DownLoadThread.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.management.jfr; + +import java.io.IOException; +import java.time.Instant; +import java.util.HashMap; +import java.util.Map; + +final class DownLoadThread extends Thread { + private final RemoteRecordingStream stream; + private final Instant startTime; + private final Instant endTime; + private final DiskRepository diskRepository; + + DownLoadThread(RemoteRecordingStream stream) { + this.stream = stream; + this.startTime = stream.startTime; + this.endTime = stream.endTime; + this.diskRepository = stream.repository; + } + + public void run() { + try { + Map options = new HashMap<>(); + if (startTime != null) { + options.put("startTime", startTime.toString()); + } + if (endTime != null) { + options.put("endTime", endTime.toString()); + } + options.put("streamVersion", "1.0"); + long streamId = this.stream.mbean.openStream(stream.recordingId, options); + while (!stream.isClosed()) { + byte[] bytes = stream.mbean.readStream(streamId); + if (bytes == null) { + return; + } + if (bytes.length != 0) { + diskRepository.write(bytes); + } else { + takeNap(); + } + } + } catch (IOException ioe) { + // ignore + } finally { + diskRepository.complete(); + } + } + + private void takeNap() { + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { + // ignore + } + } +} diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBean.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBean.java index 4aebdede921..4f83786709f 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBean.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBean.java @@ -346,12 +346,22 @@ public interface FlightRecorderMXBean extends PlatformManagedObject { * {@code "50000"},
    * {@code "1000000"},
    * + * + * {@code streamVersion} + * Specifies format to use when reading data from a running recording + * + * {@code "1.0"} + * A version number with a major and minor.
    + *
    + * To be able to read from a running recording the value must be set + * {@code "1.0"} + * * * * If an option is omitted from the map the default value is used. *

    * The recording with the specified ID must be stopped before a stream can - * be opened. This restriction might be lifted in future releases. + * be opened, unless the option {@code "streamVersion"} is specified. * * @param recordingId ID of the recording to open the stream for * diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBeanImpl.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBeanImpl.java index 115ed8cd87f..dfe7ecaca84 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBeanImpl.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBeanImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, 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 @@ -71,6 +71,7 @@ import jdk.jfr.Recording; import jdk.jfr.RecordingState; import jdk.jfr.internal.management.ManagementSupport; +import jdk.jfr.internal.management.StreamManager; // Instantiated by service provider final class FlightRecorderMXBeanImpl extends StandardEmitterMBean implements FlightRecorderMXBean, NotificationEmitter { @@ -147,6 +148,15 @@ public long openStream(long id, Map options) throws IOException Instant starttime = MBeanUtils.parseTimestamp(s.get("startTime"), Instant.MIN); Instant endtime = MBeanUtils.parseTimestamp(s.get("endTime"), Instant.MAX); int blockSize = MBeanUtils.parseBlockSize(s.get("blockSize"), StreamManager.DEFAULT_BLOCK_SIZE); + String version = s.get("streamVersion"); + if (version != null) { + if ("1.0".equals(version)) { + Recording r = getRecording(id); + return streamHandler.createOngoing(r, blockSize, starttime, endtime).getId(); + } + throw new IllegalArgumentException("Unsupported stream version " + version); + } + InputStream is = getExistingRecording(id).getStream(starttime, endtime); if (is == null) { throw new IOException("No recording data available"); diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/MBeanUtils.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/MBeanUtils.java index 9cb6424230e..31d6b7b5e9e 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/MBeanUtils.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/MBeanUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, 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 @@ -140,4 +140,3 @@ public static String destination(Recording recording, String destination) throws } } } - diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/RemoteRecordingStream.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/RemoteRecordingStream.java new file mode 100644 index 00000000000..c5af59d1776 --- /dev/null +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/RemoteRecordingStream.java @@ -0,0 +1,563 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.management.jfr; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Consumer; +import java.security.AccessControlException; +import javax.management.JMX; +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; + +import jdk.jfr.Configuration; +import jdk.jfr.EventSettings; +import jdk.jfr.EventType; +import jdk.jfr.Recording; +import jdk.jfr.consumer.EventStream; +import jdk.jfr.consumer.MetadataEvent; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.internal.management.EventSettingsModifier; +import jdk.jfr.internal.management.ManagementSupport; +import jdk.jfr.internal.management.EventByteStream; + +/** + * An implementation of an {@link EventStream} that can serialize events over + * the network using an {@link MBeanServerConnection}. + *

    + * The following example shows how to record garbage collection pauses and CPU + * usage on a remote host and print the events to standard out. + * + *

    + * {
    + *     {@literal
    + *     String host = "com.example";
    + *     int port = 4711;
    + *
    + *     String url = "service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/jmxrmi";
    + *
    + *     JMXServiceURL u = new JMXServiceURL(url);
    + *     JMXConnector c = JMXConnectorFactory.connect(u);
    + *     MBeanServerConnection conn = c.getMBeanServerConnection();
    + *
    + *     try (var rs = new RemoteRecordingStream(conn)) {
    + *         rs.enable("jdk.GCPhasePause").withoutThreshold();
    + *         rs.enable("jdk.CPULoad").withPeriod(Duration.ofSeconds(1));
    + *         rs.onEvent("jdk.CPULoad", System.out::println);
    + *         rs.onEvent("jdk.GCPhasePause", System.out::println);
    + *         rs.start();
    + *     }
    + * }
    + * 
    + * + * @since 16 + */ +public final class RemoteRecordingStream implements EventStream { + private static final String ENABLED = "enabled"; + + static final class RemoteSettings implements EventSettingsModifier { + + private final FlightRecorderMXBean mbean; + private final long recordingId; + + RemoteSettings(FlightRecorderMXBean mbean, long recordingId) { + this.mbean = mbean; + this.recordingId = recordingId; + } + + @Override + public void with(String name, String value) { + Objects.requireNonNull(name); + Objects.requireNonNull(value); + // FlightRecorderMXBean implementation always returns + // new instance of Map so no need to create new here. + Map newSettings = getEventSettings(); + newSettings.put(name, value); + mbean.setRecordingSettings(recordingId, newSettings); + } + + @Override + public Map toMap() { + return getEventSettings(); + } + + private Map getEventSettings() { + return mbean.getRecordingSettings(recordingId); + } + } + + // Reference to stream is released when EventStream::close is called + final static class ChunkConsumer implements Consumer { + + private final DiskRepository repository; + + ChunkConsumer(DiskRepository repository) { + this.repository = repository; + } + + @Override + public void accept(Long endNanos) { + Instant t = ManagementSupport.epochNanosToInstant(endNanos); + repository.onChunkComplete(t); + } + } + + private static final ObjectName OBJECT_NAME = MBeanUtils.createObjectName(); + + final Path path; + final FlightRecorderMXBean mbean; + final long recordingId; + final EventStream stream; + final AccessControlContext accessControllerContext; + final DiskRepository repository; + final Instant creationTime; + volatile Instant startTime; + volatile Instant endTime; + volatile boolean closed; + + /** + * Creates an event stream that operates against a {@link MBeanServerConnection} + * that has a registered {@link FlightRecorderMXBean}. + *

    + * To configure event settings, use {@link #setSettings(Map)}. + * + * @param connection the {@code MBeanServerConnection} where the + * {@code FlightRecorderMXBean} is registered, not + * {@code null} + * + * @throws IOException if a stream can't be opened, an I/O error occurs + * when trying to access the repository or the + * {@code FlightRecorderMXBean} + * + * @throws SecurityException if a security manager exists and its + * {@code checkRead} method denies read access to the + * directory, or files in the directory. + */ + public RemoteRecordingStream(MBeanServerConnection connection) throws IOException { + this(connection, makeTempDirectory(), true); + } + + /** + * Creates an event stream that operates against a {@link MBeanServerConnection} + * that has a registered {@link FlightRecorderMXBean}. + *

    + * To configure event settings, use {@link #setSettings(Map)}. + * + * @param connection the {@code MBeanServerConnection} where the + * {@code FlightRecorderMXBean} is registered, not + * {@code null} + * + * @param directory the directory to store event data that is downloaded, not + * {@code null} + * + * @throws IOException if a stream can't be opened, an I/O error occurs + * when trying to access the repository or the + * {@code FlightRecorderMXBean} + * + * @throws SecurityException if a security manager exists and its + * {@code checkRead} method denies read access to the + * directory, or files in the directory. + */ + public RemoteRecordingStream(MBeanServerConnection connection, Path directory) throws IOException { + this(connection, directory, false); + } + + private RemoteRecordingStream(MBeanServerConnection connection, Path dir, boolean delete) throws IOException { + Objects.requireNonNull(connection); + Objects.requireNonNull(dir); + accessControllerContext = AccessController.getContext(); + // Make sure users can't implement malicious version of a Path object. + path = Paths.get(dir.toString()); + if (!Files.exists(path)) { + throw new IOException("Download directory doesn't exist"); + } + + if (!Files.isDirectory(path)) { + throw new IOException("Download location must be a directory"); + } + checkFileAccess(path); + creationTime = Instant.now(); + mbean = createProxy(connection); + recordingId = createRecording(); + stream = ManagementSupport.newEventDirectoryStream(accessControllerContext, path, configurations(mbean)); + stream.setStartTime(Instant.MIN); + repository = new DiskRepository(path, delete); + ManagementSupport.setOnChunkCompleteHandler(stream, new ChunkConsumer(repository)); + } + + private List configurations(FlightRecorderMXBean mbean) { + List cis = mbean.getConfigurations(); + List confs = new ArrayList<>(cis.size()); + for (ConfigurationInfo ci : cis) { + confs.add(ManagementSupport.newConfiguration(ci.getName(), ci.getLabel(), ci.getDescription(), + ci.getProvider(), ci.getSettings(), ci.getContents())); + } + return Collections.unmodifiableList(confs); + } + + @Override + public void onMetadata(Consumer action) { + stream.onMetadata(action); + } + + private static void checkFileAccess(Path directory) throws IOException { + RandomAccessFile f = null; + try { + Path testFile = directory.resolve("test-access"); + f = new RandomAccessFile(testFile.toFile(), "rw"); + f.write(0); + f.seek(0); + f.read(); + f.close(); + Files.delete(testFile); + } catch (Exception e) { + closeSilently(f); + throw new IOException("Could not read/write/delete in directory" + directory + " :" + e.getMessage()); + } + } + + private static void closeSilently(RandomAccessFile f) { + if (f == null) { + return; + } + try { + f.close(); + } catch (IOException ioe) { + // ignore + } + } + + private static FlightRecorderMXBean createProxy(MBeanServerConnection connection) throws IOException { + try { + return JMX.newMXBeanProxy(connection, OBJECT_NAME, FlightRecorderMXBean.class); + } catch (Exception e) { + throw new IOException("Could not create proxy for FlightRecorderMXBean: " + e.getMessage(), e); + } + } + + private long createRecording() throws IOException { + try { + long id = mbean.newRecording(); + Map options = new HashMap<>(); + options.put("name", EventByteStream.NAME + ": " + creationTime); + mbean.setRecordingOptions(id, options); + return id; + } catch (Exception e) { + throw new IOException("Could not create new recording: " + e.getMessage(), e); + } + } + + private Map getRecordingOptions() throws IOException { + try { + return mbean.getRecordingOptions(recordingId); + } catch (Exception e) { + throw new IOException("Could not get recording options: " + e.getMessage(), e); + } + } + + /** + * Replaces all settings for this recording stream. + *

    + * The following example connects to a remote host and stream events using + * settings from the "default" configuration. + * + *

    +     * {
    +     *     {@literal
    +     *
    +     *     String host = "com.example";
    +     *     int port = 4711;
    +     *
    +     *     String url = "service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/jmxrmi";
    +     *
    +     *     JMXServiceURL u = new JMXServiceURL(url);
    +     *     JMXConnector c = JMXConnectorFactory.connect(u);
    +     *     MBeanServerConnection conn = c.getMBeanServerConnection();
    +     *
    +     *     try (final var rs = new RemoteRecordingStream(conn)) {
    +     *         rs.onMetadata(e -> {
    +     *             for (Configuration c : e.getConfigurations()) {
    +     *                 if (c.getName().equals("default")) {
    +     *                     rs.setSettings(c.getSettings());
    +     *                 }
    +     *             }
    +     *         });
    +     *         rs.onEvent(System.out::println);
    +     *         rs.start();
    +     *     }
    +     *
    +     * }
    +     * 
    + * + * @param settings the settings to set, not {@code null} + * + * @see Recording#setSettings(Map) + */ + public void setSettings(Map settings) { + Objects.requireNonNull(settings); + try { + mbean.setRecordingSettings(recordingId, settings); + } catch (Exception e) { + ManagementSupport.logDebug(e.getMessage()); + close(); + } + }; + + /** + * Disables event with the specified name. + *

    + * If multiple events with same name (for example, the same class is loaded in + * different class loaders), then all events that match the name are disabled. + * + * @param name the settings for the event, not {@code null} + * + * @return an event setting for further configuration, not {@code null} + * + */ + public EventSettings disable(String name) { + Objects.requireNonNull(name); + EventSettings s = ManagementSupport.newEventSettings(new RemoteSettings(mbean, recordingId)); + try { + return s.with(name + "#" + ENABLED, "false"); + } catch (Exception e) { + ManagementSupport.logDebug(e.getMessage()); + close(); + return s; + } + } + + /** + * Enables the event with the specified name. + *

    + * If multiple events have the same name (for example, the same class is loaded + * in different class loaders), then all events that match the name are enabled. + * + * @param name the settings for the event, not {@code null} + * + * @return an event setting for further configuration, not {@code null} + * + * @see EventType + */ + public EventSettings enable(String name) { + Objects.requireNonNull(name); + EventSettings s = ManagementSupport.newEventSettings(new RemoteSettings(mbean, recordingId)); + try { + return s.with(name + "#" + ENABLED, "true"); + } catch (Exception e) { + ManagementSupport.logDebug(e.getMessage()); + close(); + return s; + } + } + + /** + * Determines how far back data is kept for the stream. + *

    + * To control the amount of recording data stored on disk, the maximum length of + * time to retain the data can be specified. Data stored on disk that is older + * than the specified length of time is removed by the Java Virtual Machine + * (JVM). + *

    + * If neither maximum limit or the maximum age is set, the size of the recording + * may grow indefinitely if events are not consumed. + * + * @param maxAge the length of time that data is kept, or {@code null} if + * infinite + * + * @throws IllegalArgumentException if {@code maxAge} is negative + * + * @throws IllegalStateException if the recording is in the {@code CLOSED} + * state + */ + public void setMaxAge(Duration maxAge) { + Objects.requireNonNull(maxAge); + repository.setMaxAge(maxAge); + } + + /** + * Determines how much data is kept for the stream. + *

    + * To control the amount of recording data that is stored on disk, the maximum + * amount of data to retain can be specified. When the maximum limit is + * exceeded, the Java Virtual Machine (JVM) removes the oldest chunk to make + * room for a more recent chunk. + *

    + * If neither maximum limit or the maximum age is set, the size of the recording + * may grow indefinitely if events are not consumed. + *

    + * The size is measured in bytes. + * + * @param maxSize the amount of data to retain, {@code 0} if infinite + * + * @throws IllegalArgumentException if {@code maxSize} is negative + * + * @throws IllegalStateException if the recording is in {@code CLOSED} state + */ + public void setMaxSize(long maxSize) { + if (maxSize < 0) { + throw new IllegalArgumentException("Max size of recording can't be negative"); + } + repository.setMaxSize(maxSize); + } + + @Override + public void onEvent(Consumer action) { + stream.onEvent(action); + } + + @Override + public void onEvent(String eventName, Consumer action) { + stream.onEvent(eventName, action); + } + + @Override + public void onFlush(Runnable action) { + stream.onFlush(action); + } + + @Override + public void onError(Consumer action) { + stream.onError(action); + } + + @Override + public void onClose(Runnable action) { + stream.onClose(action); + } + + @Override + public void close() { + if (closed) { + return; + } + closed = true; + ManagementSupport.setOnChunkCompleteHandler(stream, null); + stream.close(); + try { + mbean.closeRecording(recordingId); + } catch (IOException e) { + ManagementSupport.logDebug(e.getMessage()); + } + try { + repository.close(); + } catch (IOException e) { + ManagementSupport.logDebug(e.getMessage()); + } + } + + @Override + public boolean remove(Object action) { + return stream.remove(action); + } + + @Override + public void setReuse(boolean reuse) { + stream.setReuse(reuse); + } + + @Override + public void setOrdered(boolean ordered) { + stream.setOrdered(ordered); + } + + @Override + public void setStartTime(Instant startTime) { + stream.setStartTime(startTime); + this.startTime = startTime; + } + + @Override + public void setEndTime(Instant endTime) { + stream.setEndTime(endTime); + this.endTime = endTime; + } + + @Override + public void start() { + try { + try { + mbean.startRecording(recordingId); + } catch (IllegalStateException ise) { + throw ise; + } + startDownload(); + } catch (Exception e) { + ManagementSupport.logDebug(e.getMessage()); + close(); + return; + } + stream.start(); + } + + @Override + public void startAsync() { + stream.startAsync(); + try { + mbean.startRecording(recordingId); + startDownload(); + } catch (Exception e) { + ManagementSupport.logDebug(e.getMessage()); + close(); + } + } + + @Override + public void awaitTermination(Duration timeout) throws InterruptedException { + stream.awaitTermination(timeout); + } + + @Override + public void awaitTermination() throws InterruptedException { + stream.awaitTermination(); + } + + private static Path makeTempDirectory() throws IOException { + return Files.createTempDirectory("jfr-streaming"); + } + + private void startDownload() { + Thread downLoadThread = new DownLoadThread(this); + downLoadThread.setName("JFR: Download Thread " + creationTime); + downLoadThread.start(); + } + + boolean isClosed() { + return closed; + } +} diff --git a/src/jdk.management.jfr/share/classes/module-info.java b/src/jdk.management.jfr/share/classes/module-info.java index a76552c4c2e..6264ecac751 100644 --- a/src/jdk.management.jfr/share/classes/module-info.java +++ b/src/jdk.management.jfr/share/classes/module-info.java @@ -30,7 +30,7 @@ * @since 9 */ module jdk.management.jfr { - requires jdk.jfr; + requires transitive jdk.jfr; requires jdk.management; requires transitive java.management; diff --git a/src/jdk.unsupported/share/classes/sun/misc/Unsafe.java b/src/jdk.unsupported/share/classes/sun/misc/Unsafe.java index e62f6338a50..bc29a0f7b88 100644 --- a/src/jdk.unsupported/share/classes/sun/misc/Unsafe.java +++ b/src/jdk.unsupported/share/classes/sun/misc/Unsafe.java @@ -867,15 +867,17 @@ public int pageSize() { *

  • InterfaceMethodRef: (NYI) a method handle to invoke on that call site's arguments * * - * @deprecated Use the {@link java.lang.invoke.MethodHandles.Lookup#defineHiddenClass(byte[], boolean, MethodHandles.Lookup.ClassOption...)} - * method. + * @deprecated Use {@link java.lang.invoke.MethodHandles.Lookup#defineHiddenClass(byte[], boolean, MethodHandles.Lookup.ClassOption...)} + * or {@link java.lang.invoke.MethodHandles.Lookup#defineHiddenClassWithClassData(byte[], Object, boolean, MethodHandles.Lookup.ClassOption...)} + * instead. * * @param hostClass context for linkage, access control, protection domain, and class loader * @param data bytes of a class file * @param cpPatches where non-null entries exist, they replace corresponding CP entries in data */ @ForceInline - @Deprecated(since = "15", forRemoval = false) + @Deprecated(since = "15", forRemoval = true) + @SuppressWarnings("removal") public Class defineAnonymousClass(Class hostClass, byte[] data, Object[] cpPatches) { return theInternalUnsafe.defineAnonymousClass(hostClass, data, cpPatches); } diff --git a/test/hotspot/gtest/opto/test_regmask.cpp b/test/hotspot/gtest/opto/test_regmask.cpp index 480c13e90c2..afe92daff12 100644 --- a/test/hotspot/gtest/opto/test_regmask.cpp +++ b/test/hotspot/gtest/opto/test_regmask.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "opto/opcodes.hpp" #include "opto/regmask.hpp" #include "unittest.hpp" @@ -146,7 +147,8 @@ TEST_VM(RegMask, is_bound1) { ASSERT_FALSE(rm.is_bound1()); for (int i = 0; i < RegMask::CHUNK_SIZE - 1; i++) { rm.Insert(i); - ASSERT_TRUE(rm.is_bound1()); + ASSERT_TRUE(rm.is_bound1()) << "Index " << i; + ASSERT_TRUE(rm.is_bound(Op_RegI)) << "Index " << i; contains_expected_num_of_registers(rm, 1); rm.Remove(i); } @@ -154,3 +156,43 @@ TEST_VM(RegMask, is_bound1) { rm.set_AllStack(); ASSERT_FALSE(rm.is_bound1()); } + +TEST_VM(RegMask, is_bound_pair) { + RegMask rm; + ASSERT_TRUE(rm.is_bound_pair()); + for (int i = 0; i < RegMask::CHUNK_SIZE - 2; i++) { + rm.Insert(i); + rm.Insert(i + 1); + ASSERT_TRUE(rm.is_bound_pair()) << "Index " << i; + ASSERT_TRUE(rm.is_bound_set(2)) << "Index " << i; + ASSERT_TRUE(rm.is_bound(Op_RegI)) << "Index " << i; + contains_expected_num_of_registers(rm, 2); + rm.Clear(); + } + // A pair with the AllStack bit does not count as a bound pair + rm.Clear(); + rm.Insert(RegMask::CHUNK_SIZE - 2); + rm.Insert(RegMask::CHUNK_SIZE - 1); + ASSERT_FALSE(rm.is_bound_pair()); +} + +TEST_VM(RegMask, is_bound_set) { + RegMask rm; + for (int size = 1; size <= 16; size++) { + ASSERT_TRUE(rm.is_bound_set(size)); + for (int i = 0; i < RegMask::CHUNK_SIZE - size; i++) { + for (int j = i; j < i + size; j++) { + rm.Insert(j); + } + ASSERT_TRUE(rm.is_bound_set(size)) << "Size " << size << " Index " << i; + contains_expected_num_of_registers(rm, size); + rm.Clear(); + } + // A set with the AllStack bit does not count as a bound set + for (int j = RegMask::CHUNK_SIZE - size; j < RegMask::CHUNK_SIZE; j++) { + rm.Insert(j); + } + ASSERT_FALSE(rm.is_bound_set(size)); + rm.Clear(); + } +} \ No newline at end of file diff --git a/test/hotspot/gtest/runtime/test_os.cpp b/test/hotspot/gtest/runtime/test_os.cpp index a084e27119a..4795a78407e 100644 --- a/test/hotspot/gtest/runtime/test_os.cpp +++ b/test/hotspot/gtest/runtime/test_os.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, 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 @@ -120,10 +120,10 @@ TEST(os, test_random) { unsigned int seed = 1; // tty->print_cr("seed %ld for %ld repeats...", seed, reps); - os::init_random(seed); int num; for (int k = 0; k < reps; k++) { - num = os::random(); + // Use next_random so the calculation is stateless. + num = seed = os::next_random(seed); double u = (double)num / m; ASSERT_TRUE(u >= 0.0 && u <= 1.0) << "bad random number!"; @@ -148,7 +148,6 @@ TEST(os, test_random) { ASSERT_LT(t, eps) << "bad variance"; } - #ifdef ASSERT TEST_VM_ASSERT_MSG(os, page_size_for_region_with_zero_min_pages, "sanity") { size_t region_size = 16 * os::vm_page_size(); diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index b11c209a8a5..96f90907d28 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -843,6 +843,7 @@ jdk/jfr/api/recording/event/TestReEnableName.java 8256482 windows- jdk/jfr/event/runtime/TestNetworkUtilizationEvent.java 8228990,8229370 generic-all jdk/jfr/event/compiler/TestCodeSweeper.java 8225209 generic-all jdk/jfr/event/os/TestThreadContextSwitches.java 8247776 windows-all +jdk/jfr/jmx/streaming/TestRotate.java 8257215 generic-all ############################################################################ diff --git a/test/jdk/java/lang/invoke/AccessControlTest.java b/test/jdk/java/lang/invoke/AccessControlTest.java index c6be6179192..8555011e8b5 100644 --- a/test/jdk/java/lang/invoke/AccessControlTest.java +++ b/test/jdk/java/lang/invoke/AccessControlTest.java @@ -148,7 +148,8 @@ else if (lookupModes == (PUBLIC|PACKAGE|PRIVATE) || lookupModes == (PUBLIC|MODULE|PACKAGE|PRIVATE)) suffix = "/private"; else if (lookupModes == (PUBLIC|PACKAGE|PRIVATE|PROTECTED) - || lookupModes == (PUBLIC|MODULE|PACKAGE|PRIVATE|PROTECTED)) + || lookupModes == (PUBLIC|MODULE|PACKAGE|PRIVATE|PROTECTED) + || lookupModes == (PUBLIC|MODULE|PACKAGE|PRIVATE|PROTECTED|ORIGINAL)) suffix = ""; else suffix = "/#"+Integer.toHexString(lookupModes); @@ -160,9 +161,11 @@ else if (lookupModes == (PUBLIC|PACKAGE|PRIVATE|PROTECTED) * Creates a lookup on the specified new lookup class. * [A1] The resulting object will report the specified * class as its own {@link #lookupClass lookupClass}. - * [A2] However, the resulting {@code Lookup} object is guaranteed + * [A1-a] However, the resulting {@code Lookup} object is guaranteed * to have no more access capabilities than the original. * In particular, access capabilities can be lost as follows:
      + * [A2] If the new lookup class is not the same as the old lookup class, + * then {@link #ORIGINAL ORIGINAL} access is lost. * [A3] If the new lookup class is in a different module from the old one, * i.e. {@link #MODULE MODULE} access is lost. * [A4] If the new lookup class is in a different package @@ -227,11 +230,14 @@ public LookupCase in(Class c2) { } if (!accessible) { // no access to c2; lose all access. - changed |= (PUBLIC|MODULE|PACKAGE|PRIVATE|PROTECTED|UNCONDITIONAL); // [A6] + changed |= (PUBLIC|MODULE|PACKAGE|PRIVATE|PROTECTED|UNCONDITIONAL); // [A7] + } + if (!sameClass) { + changed |= ORIGINAL; // [A2] } if (m2 != m1 && m0 != m1) { // hop to a third module; lose all access - changed |= (PUBLIC|MODULE|PACKAGE|PRIVATE|PROTECTED); // [A7] + changed |= (PUBLIC|MODULE|PACKAGE|PRIVATE|PROTECTED); // [A8] } if (!sameModule) { changed |= MODULE; // [A3] @@ -254,20 +260,21 @@ public LookupCase in(Class c2) { if ((modes1 & UNCONDITIONAL) != 0) plc = null; // [A8] LookupCase l2 = new LookupCase(c2, plc, modes2); assert(l2.lookupClass() == c2); // [A1] - assert((modes1 | modes2) == modes1); // [A2] (no elevation of access) + assert((modes1 | modes2) == modes1); // [A1-a] (no elevation of access) assert(l2.prevLookupClass() == null || (modes2 & MODULE) == 0); return l2; } LookupCase dropLookupMode(int modeToDrop) { int oldModes = lookupModes(); - int newModes = oldModes & ~(modeToDrop | PROTECTED); + int newModes = oldModes & ~(modeToDrop | PROTECTED | ORIGINAL); switch (modeToDrop) { case PUBLIC: newModes &= ~(MODULE|PACKAGE|PROTECTED|PRIVATE); break; case MODULE: newModes &= ~(PACKAGE|PRIVATE); break; case PACKAGE: newModes &= ~(PRIVATE); break; case PROTECTED: case PRIVATE: + case ORIGINAL: case UNCONDITIONAL: break; default: throw new IllegalArgumentException(modeToDrop + " is not a valid mode to drop"); } diff --git a/test/jdk/java/lang/invoke/CallerSensitiveAccess.java b/test/jdk/java/lang/invoke/CallerSensitiveAccess.java index a8aa649059e..894c7413805 100644 --- a/test/jdk/java/lang/invoke/CallerSensitiveAccess.java +++ b/test/jdk/java/lang/invoke/CallerSensitiveAccess.java @@ -117,6 +117,37 @@ public void testLookupUnreflect(@NoInjection Method method, String desc) throws MethodHandles.publicLookup().unreflect(method); } + /** + * Using a Lookup with no original access that can't lookup caller-sensitive + * method + */ + @Test(dataProvider = "callerSensitiveMethods", + expectedExceptions = IllegalAccessException.class) + public void testLookupNoOriginalAccessFind(@NoInjection Method method, String desc) throws Exception { + Lookup lookup = MethodHandles.lookup().dropLookupMode(Lookup.ORIGINAL); + assertTrue(lookup.hasFullPrivilegeAccess()); + Class refc = method.getDeclaringClass(); + String name = method.getName(); + MethodType mt = MethodType.methodType(method.getReturnType(), method.getParameterTypes()); + if (Modifier.isStatic(method.getModifiers())) { + lookup.findStatic(refc, name, mt); + } else { + lookup.findVirtual(refc, name, mt); + } + } + + /** + * Using a Lookup with no original access that can't unreflect caller-sensitive + * method + */ + @Test(dataProvider = "callerSensitiveMethods", + expectedExceptions = IllegalAccessException.class) + public void testLookupNoOriginalAccessUnreflect(@NoInjection Method method, String desc) throws Exception { + Lookup lookup = MethodHandles.lookup().dropLookupMode(Lookup.ORIGINAL); + assertTrue(lookup.hasFullPrivilegeAccess()); + lookup.unreflect(method); + } + // -- Test method handles to setAccessible -- private int aField; diff --git a/test/jdk/java/lang/invoke/DropLookupModeTest.java b/test/jdk/java/lang/invoke/DropLookupModeTest.java index 1d3af286e0e..1a4c311be8b 100644 --- a/test/jdk/java/lang/invoke/DropLookupModeTest.java +++ b/test/jdk/java/lang/invoke/DropLookupModeTest.java @@ -44,7 +44,7 @@ public class DropLookupModeTest { public void testBasic() { final Lookup fullPowerLookup = MethodHandles.lookup(); final Class lc = fullPowerLookup.lookupClass(); - assertTrue(fullPowerLookup.lookupModes() == (PUBLIC|MODULE|PACKAGE|PROTECTED|PRIVATE)); + assertTrue(fullPowerLookup.lookupModes() == (PUBLIC|MODULE|PACKAGE|PROTECTED|PRIVATE|ORIGINAL)); Lookup lookup = fullPowerLookup.dropLookupMode(PRIVATE); assertTrue(lookup.lookupClass() == lc); @@ -78,7 +78,7 @@ public void testBasic() { public void testReducingAccess() { Lookup lookup = MethodHandles.lookup(); final Class lc = lookup.lookupClass(); - assertTrue(lookup.lookupModes() == (PUBLIC|MODULE|PACKAGE|PROTECTED|PRIVATE)); + assertTrue(lookup.lookupModes() == (PUBLIC|MODULE|PACKAGE|PROTECTED|PRIVATE|ORIGINAL)); lookup = lookup.dropLookupMode(PROTECTED); assertTrue(lookup.lookupClass() == lc); diff --git a/test/jdk/java/lang/invoke/MethodHandles/classData/ClassDataTest.java b/test/jdk/java/lang/invoke/MethodHandles/classData/ClassDataTest.java new file mode 100644 index 00000000000..ab5d81d4ec5 --- /dev/null +++ b/test/jdk/java/lang/invoke/MethodHandles/classData/ClassDataTest.java @@ -0,0 +1,510 @@ +/* + * Copyright (c) 2020, 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 8230501 + * @library /test/lib + * @modules java.base/jdk.internal.org.objectweb.asm + * @run testng/othervm ClassDataTest + */ + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UncheckedIOException; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodType; +import java.lang.reflect.Method; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import jdk.internal.org.objectweb.asm.*; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static java.lang.invoke.MethodHandles.Lookup.*; +import static jdk.internal.org.objectweb.asm.Opcodes.*; +import static org.testng.Assert.*; + +public class ClassDataTest { + private static final Lookup LOOKUP = MethodHandles.lookup(); + + @Test + public void testOriginalAccess() throws IllegalAccessException { + Lookup lookup = hiddenClass(20); + assertTrue(lookup.hasFullPrivilegeAccess()); + + int value = MethodHandles.classData(lookup, "_", int.class); + assertEquals(value, 20); + + Integer i = MethodHandles.classData(lookup, "_", Integer.class); + assertEquals(i.intValue(), 20); + } + + /* + * A lookup class with no class data. + */ + @Test + public void noClassData() throws IllegalAccessException { + assertNull(MethodHandles.classData(LOOKUP, "_", Object.class)); + } + + @DataProvider(name = "teleportedLookup") + private Object[][] teleportedLookup() throws ReflectiveOperationException { + Lookup lookup = hiddenClass(30); + Class hc = lookup.lookupClass(); + assertClassData(lookup, 30); + + int fullAccess = PUBLIC|PROTECTED|PACKAGE|MODULE|PRIVATE; + return new Object[][] { + new Object[] { MethodHandles.privateLookupIn(hc, LOOKUP), fullAccess}, + new Object[] { LOOKUP.in(hc), fullAccess & ~(PROTECTED|PRIVATE) }, + new Object[] { lookup.dropLookupMode(PRIVATE), fullAccess & ~(PROTECTED|PRIVATE) }, + }; + } + + @Test(dataProvider = "teleportedLookup", expectedExceptions = { IllegalAccessException.class }) + public void illegalAccess(Lookup lookup, int access) throws IllegalAccessException { + int lookupModes = lookup.lookupModes(); + assertTrue((lookupModes & ORIGINAL) == 0); + assertEquals(lookupModes, access); + MethodHandles.classData(lookup, "_", int.class); + } + + @Test(expectedExceptions = { ClassCastException.class }) + public void incorrectType() throws IllegalAccessException { + Lookup lookup = hiddenClass(20); + MethodHandles.classData(lookup, "_", Long.class); + } + + @Test(expectedExceptions = { IndexOutOfBoundsException.class }) + public void invalidIndex() throws IllegalAccessException { + Lookup lookup = hiddenClass(List.of()); + MethodHandles.classDataAt(lookup, "_", Object.class, 0); + } + + @Test(expectedExceptions = { NullPointerException.class }) + public void unboxNull() throws IllegalAccessException { + List list = new ArrayList<>(); + list.add(null); + Lookup lookup = hiddenClass(list); + MethodHandles.classDataAt(lookup, "_", int.class, 0); + } + + @Test + public void nullElement() throws IllegalAccessException { + List list = new ArrayList<>(); + list.add(null); + Lookup lookup = hiddenClass(list); + assertTrue(MethodHandles.classDataAt(lookup, "_", Object.class, 0) == null); + } + + @Test + public void intClassData() throws ReflectiveOperationException { + ClassByteBuilder builder = new ClassByteBuilder("T1-int"); + byte[] bytes = builder.classData(ACC_PUBLIC|ACC_STATIC, int.class).build(); + Lookup lookup = LOOKUP.defineHiddenClassWithClassData(bytes, 100, true); + int value = MethodHandles.classData(lookup, "_", int.class); + assertEquals(value, 100); + // call through condy + assertClassData(lookup, 100); + } + + @Test + public void floatClassData() throws ReflectiveOperationException { + ClassByteBuilder builder = new ClassByteBuilder("T1-float"); + byte[] bytes = builder.classData(ACC_PUBLIC|ACC_STATIC, float.class).build(); + Lookup lookup = LOOKUP.defineHiddenClassWithClassData(bytes, 0.1234f, true); + float value = MethodHandles.classData(lookup, "_", float.class); + assertEquals(value, 0.1234f); + // call through condy + assertClassData(lookup, 0.1234f); + } + + @Test + public void classClassData() throws ReflectiveOperationException { + Class hc = hiddenClass(100).lookupClass(); + ClassByteBuilder builder = new ClassByteBuilder("T2"); + byte[] bytes = builder.classData(ACC_PUBLIC|ACC_STATIC, Class.class).build(); + Lookup lookup = LOOKUP.defineHiddenClassWithClassData(bytes, hc, true); + Class value = MethodHandles.classData(lookup, "_", Class.class); + assertEquals(value, hc); + // call through condy + assertClassData(lookup, hc); + } + + @Test + public void arrayClassData() throws ReflectiveOperationException { + ClassByteBuilder builder = new ClassByteBuilder("T3"); + byte[] bytes = builder.classData(ACC_PUBLIC|ACC_STATIC, String[].class).build(); + String[] colors = new String[] { "red", "yellow", "blue"}; + Lookup lookup = LOOKUP.defineHiddenClassWithClassData(bytes, colors, true); + assertClassData(lookup, colors.clone()); + // class data is modifiable and not a constant + colors[0] = "black"; + // it will get back the modified class data + String[] value = MethodHandles.classData(lookup, "_", String[].class); + assertEquals(value, colors); + // even call through condy as it's not a constant + assertClassData(lookup, colors); + } + + @Test + public void listClassData() throws ReflectiveOperationException { + ClassByteBuilder builder = new ClassByteBuilder("T4"); + byte[] bytes = builder.classDataAt(ACC_PUBLIC|ACC_STATIC, Integer.class, 2).build(); + List cd = List.of(100, 101, 102, 103); + int expected = 102; // element at index=2 + Lookup lookup = LOOKUP.defineHiddenClassWithClassData(bytes, cd, true); + int value = MethodHandles.classDataAt(lookup, "_", int.class, 2); + assertEquals(value, expected); + // call through condy + assertClassData(lookup, expected); + } + + @Test + public void arrayListClassData() throws ReflectiveOperationException { + ClassByteBuilder builder = new ClassByteBuilder("T4"); + byte[] bytes = builder.classDataAt(ACC_PUBLIC|ACC_STATIC, Integer.class, 1).build(); + ArrayList cd = new ArrayList<>(); + Stream.of(100, 101, 102, 103).forEach(cd::add); + int expected = 101; // element at index=1 + Lookup lookup = LOOKUP.defineHiddenClassWithClassData(bytes, cd, true); + int value = MethodHandles.classDataAt(lookup, "_", int.class, 1); + assertEquals(value, expected); + // call through condy + assertClassData(lookup, expected); + } + + private static Lookup hiddenClass(int value) { + ClassByteBuilder builder = new ClassByteBuilder("HC"); + byte[] bytes = builder.classData(ACC_PUBLIC|ACC_STATIC, int.class).build(); + try { + return LOOKUP.defineHiddenClassWithClassData(bytes, value, true); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + private static Lookup hiddenClass(List list) { + ClassByteBuilder builder = new ClassByteBuilder("HC"); + byte[] bytes = builder.classData(ACC_PUBLIC|ACC_STATIC, List.class).build(); + try { + return LOOKUP.defineHiddenClassWithClassData(bytes, list, true); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + @Test + public void condyInvokedFromVirtualMethod() throws ReflectiveOperationException { + ClassByteBuilder builder = new ClassByteBuilder("T5"); + // generate classData instance method + byte[] bytes = builder.classData(ACC_PUBLIC, Class.class).build(); + Lookup hcLookup = hiddenClass(100); + assertClassData(hcLookup, 100); + Class hc = hcLookup.lookupClass(); + Lookup lookup = LOOKUP.defineHiddenClassWithClassData(bytes, hc, true); + Class value = MethodHandles.classData(lookup, "_", Class.class); + assertEquals(value, hc); + // call through condy + Class c = lookup.lookupClass(); + assertClassData(lookup, c.newInstance(), hc); + } + + @Test + public void immutableListClassData() throws ReflectiveOperationException { + ClassByteBuilder builder = new ClassByteBuilder("T6"); + // generate classDataAt instance method + byte[] bytes = builder.classDataAt(ACC_PUBLIC, Integer.class, 2).build(); + List cd = List.of(100, 101, 102, 103); + int expected = 102; // element at index=2 + Lookup lookup = LOOKUP.defineHiddenClassWithClassData(bytes, cd, true); + int value = MethodHandles.classDataAt(lookup, "_", int.class, 2); + assertEquals(value, expected); + // call through condy + Class c = lookup.lookupClass(); + assertClassData(lookup, c.newInstance() ,expected); + } + + /* + * The return value of MethodHandles::classDataAt is the element + * contained in the list when the method is called. + * If MethodHandles::classDataAt is called via condy, the value + * will be captured as a constant. If the class data is modified + * after the element at the given index is computed via condy, + * subsequent LDC of such ConstantDynamic entry will return the same + * value. However, direct invocation of MethodHandles::classDataAt + * will return the modified value. + */ + @Test + public void mutableListClassData() throws ReflectiveOperationException { + ClassByteBuilder builder = new ClassByteBuilder("T7"); + // generate classDataAt instance method + byte[] bytes = builder.classDataAt(ACC_PUBLIC, MethodType.class, 0).build(); + MethodType mtype = MethodType.methodType(int.class, String.class); + List cd = new ArrayList<>(List.of(mtype)); + Lookup lookup = LOOKUP.defineHiddenClassWithClassData(bytes, cd, true); + // call through condy + Class c = lookup.lookupClass(); + assertClassData(lookup, c.newInstance(), mtype); + // modify the class data + assertTrue(cd.remove(0) == mtype); + cd.add(0, MethodType.methodType(void.class)); + MethodType newMType = cd.get(0); + // loading the element using condy returns the original value + assertClassData(lookup, c.newInstance(), mtype); + // direct invocation of MethodHandles.classDataAt returns the modified value + assertEquals(MethodHandles.classDataAt(lookup, "_", MethodType.class, 0), newMType); + } + + // helper method to extract from a class data map + public static T getClassDataEntry(Lookup lookup, String key, Class type) throws IllegalAccessException { + Map cd = MethodHandles.classData(lookup, "_", Map.class); + return type.cast(cd.get(key)); + } + + @Test + public void classDataMap() throws ReflectiveOperationException { + ClassByteBuilder builder = new ClassByteBuilder("map"); + // generate classData static method + Handle bsm = new Handle(H_INVOKESTATIC, "ClassDataTest", "getClassDataEntry", + "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;", + false); + // generate two accessor methods to get the entries from class data + byte[] bytes = builder.classData(ACC_PUBLIC|ACC_STATIC, Map.class) + .classData(ACC_PUBLIC|ACC_STATIC, "getClass", + Class.class, new ConstantDynamic("class", Type.getDescriptor(Class.class), bsm)) + .classData(ACC_PUBLIC|ACC_STATIC, "getMethod", + MethodHandle.class, new ConstantDynamic("method", Type.getDescriptor(MethodHandle.class), bsm)) + .build(); + + // generate a hidden class + Lookup hcLookup = hiddenClass(100); + Class hc = hcLookup.lookupClass(); + assertClassData(hcLookup, 100); + + MethodHandle mh = hcLookup.findStatic(hc, "classData", MethodType.methodType(int.class)); + Map cd = Map.of("class", hc, "method", mh); + Lookup lookup = LOOKUP.defineHiddenClassWithClassData(bytes, cd, true); + assertClassData(lookup, cd); + + // validate the entries from the class data map + Class c = lookup.lookupClass(); + Method m = c.getMethod("getClass"); + Class v = (Class)m.invoke(null); + assertEquals(hc, v); + + Method m1 = c.getMethod("getMethod"); + MethodHandle v1 = (MethodHandle) m1.invoke(null); + assertEquals(mh, v1); + } + + @Test(expectedExceptions = { IllegalArgumentException.class }) + public void nonDefaultName() throws ReflectiveOperationException { + ClassByteBuilder builder = new ClassByteBuilder("nonDefaultName"); + byte[] bytes = builder.classData(ACC_PUBLIC|ACC_STATIC, Class.class) + .build(); + Lookup lookup = LOOKUP.defineHiddenClassWithClassData(bytes, ClassDataTest.class, true); + assertClassData(lookup, ClassDataTest.class); + // throw IAE + MethodHandles.classData(lookup, "non_default_name", Class.class); + } + + static class ClassByteBuilder { + private static final String OBJECT_CLS = "java/lang/Object"; + private static final String MHS_CLS = "java/lang/invoke/MethodHandles"; + private static final String CLASS_DATA_BSM_DESCR = + "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;"; + private final ClassWriter cw; + private final String classname; + + /** + * A builder to generate a class file to access class data + * @param classname + */ + ClassByteBuilder(String classname) { + this.classname = classname; + this.cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); + cw.visit(V14, ACC_FINAL, classname, null, OBJECT_CLS, null); + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, OBJECT_CLS, "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + byte[] build() { + cw.visitEnd(); + byte[] bytes = cw.toByteArray(); + Path p = Paths.get(classname + ".class"); + try (OutputStream os = Files.newOutputStream(p)) { + os.write(bytes); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + return bytes; + } + + /* + * Generate classData method to load class data via condy + */ + ClassByteBuilder classData(int accessFlags, Class returnType) { + MethodType mtype = MethodType.methodType(returnType); + MethodVisitor mv = cw.visitMethod(accessFlags, + "classData", + mtype.descriptorString(), null, null); + mv.visitCode(); + Handle bsm = new Handle(H_INVOKESTATIC, MHS_CLS, "classData", + CLASS_DATA_BSM_DESCR, + false); + ConstantDynamic dynamic = new ConstantDynamic("_", Type.getDescriptor(returnType), bsm); + mv.visitLdcInsn(dynamic); + mv.visitInsn(returnType == int.class ? IRETURN : + (returnType == float.class ? FRETURN : ARETURN)); + mv.visitMaxs(0, 0); + mv.visitEnd(); + return this; + } + + /* + * Generate classDataAt method to load an element from class data via condy + */ + ClassByteBuilder classDataAt(int accessFlags, Class returnType, int index) { + MethodType mtype = MethodType.methodType(returnType); + MethodVisitor mv = cw.visitMethod(accessFlags, + "classData", + mtype.descriptorString(), null, null); + mv.visitCode(); + Handle bsm = new Handle(H_INVOKESTATIC, "java/lang/invoke/MethodHandles", "classDataAt", + "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;I)Ljava/lang/Object;", + false); + ConstantDynamic dynamic = new ConstantDynamic("_", Type.getDescriptor(returnType), bsm, index); + mv.visitLdcInsn(dynamic); + mv.visitInsn(returnType == int.class? IRETURN : ARETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + return this; + } + + ClassByteBuilder classData(int accessFlags, String name, Class returnType, ConstantDynamic dynamic) { + MethodType mtype = MethodType.methodType(returnType); + MethodVisitor mv = cw.visitMethod(accessFlags, + name, + mtype.descriptorString(), null, null); + mv.visitCode(); + mv.visitLdcInsn(dynamic); + mv.visitInsn(returnType == int.class? IRETURN : ARETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + return this; + } + } + + /* + * Load an int constant from class data via condy and + * verify it matches the given value. + */ + private void assertClassData(Lookup lookup, int value) throws ReflectiveOperationException { + Class c = lookup.lookupClass(); + Method m = c.getMethod("classData"); + int v = (int) m.invoke(null); + assertEquals(value, v); + } + + /* + * Load an int constant from class data via condy and + * verify it matches the given value. + */ + private void assertClassData(Lookup lookup, Object o, int value) throws ReflectiveOperationException { + Class c = lookup.lookupClass(); + Method m = c.getMethod("classData"); + int v = (int) m.invoke(o); + assertEquals(value, v); + } + + /* + * Load a float constant from class data via condy and + * verify it matches the given value. + */ + private void assertClassData(Lookup lookup, float value) throws ReflectiveOperationException { + Class c = lookup.lookupClass(); + Method m = c.getMethod("classData"); + float v = (float) m.invoke(null); + assertEquals(value, v); + } + + /* + * Load a Class constant from class data via condy and + * verify it matches the given value. + */ + private void assertClassData(Lookup lookup, Class value) throws ReflectiveOperationException { + Class c = lookup.lookupClass(); + Method m = c.getMethod("classData"); + Class v = (Class)m.invoke(null); + assertEquals(value, v); + } + + /* + * Load a Class from class data via condy and + * verify it matches the given value. + */ + private void assertClassData(Lookup lookup, Object o, Class value) throws ReflectiveOperationException { + Class c = lookup.lookupClass(); + Method m = c.getMethod("classData"); + Object v = m.invoke(o); + assertEquals(value, v); + } + + /* + * Load an Object from class data via condy and + * verify it matches the given value. + */ + private void assertClassData(Lookup lookup, Object value) throws ReflectiveOperationException { + Class c = lookup.lookupClass(); + Method m = c.getMethod("classData"); + Object v = m.invoke(null); + assertEquals(value, v); + } + + /* + * Load an Object from class data via condy and + * verify it matches the given value. + */ + private void assertClassData(Lookup lookup, Object o, Object value) throws ReflectiveOperationException { + Class c = lookup.lookupClass(); + Method m = c.getMethod("classData"); + Object v = m.invoke(o); + assertEquals(value, v); + } +} + + diff --git a/test/jdk/java/lang/invoke/MethodHandles/privateLookupIn/test/p/PrivateLookupInTests.java b/test/jdk/java/lang/invoke/MethodHandles/privateLookupIn/test/p/PrivateLookupInTests.java index fe39676e24e..b17204de013 100644 --- a/test/jdk/java/lang/invoke/MethodHandles/privateLookupIn/test/p/PrivateLookupInTests.java +++ b/test/jdk/java/lang/invoke/MethodHandles/privateLookupIn/test/p/PrivateLookupInTests.java @@ -39,7 +39,6 @@ @Test public class PrivateLookupInTests { - /** * A public and non-public types in the test module but in a different * package to the test class. @@ -75,6 +74,7 @@ public void testAllAccessCallerSameModule() throws Throwable { Lookup lookup = MethodHandles.privateLookupIn(nonPublicType, MethodHandles.lookup()); assertTrue(lookup.lookupClass() == nonPublicType); assertTrue(lookup.hasFullPrivilegeAccess()); + assertTrue((lookup.lookupModes() & ORIGINAL) == 0); // get obj field MethodHandle mh = lookup.findStaticGetter(nonPublicType, "obj", Object.class); @@ -88,6 +88,7 @@ public void testReducedAccessCallerSameModule() throws Throwable { assertTrue((caller.lookupModes() & PRIVATE) == 0); assertTrue((caller.lookupModes() & PACKAGE) == 0); assertTrue((caller.lookupModes() & MODULE) != 0); + assertTrue((caller.lookupModes() & ORIGINAL) == 0); Lookup lookup = MethodHandles.privateLookupIn(nonPublicType, caller); } @@ -113,8 +114,8 @@ public void testTargetClassInOpenModule() throws Throwable { Lookup lookup = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup()); assertTrue(lookup.lookupClass() == clazz); - assertTrue((lookup.lookupModes() & PRIVATE) != 0); - assertFalse(lookup.hasFullPrivilegeAccess()); + assertTrue((lookup.lookupModes() & PRIVATE) == PRIVATE); + assertTrue((lookup.lookupModes() & MODULE) == 0); // get obj field MethodHandle mh = lookup.findStaticGetter(clazz, "obj", Object.class); @@ -138,7 +139,8 @@ public void testTargetClassInUnnamedModule() throws Throwable { thisModule.addReads(clazz.getModule()); Lookup lookup = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup()); assertTrue(lookup.lookupClass() == clazz); - assertTrue((lookup.lookupModes() & PRIVATE) != 0); + assertTrue((lookup.lookupModes() & PRIVATE) == PRIVATE); + assertTrue((lookup.lookupModes() & MODULE) == 0); } // test does not read m2, m2 opens p2 to test diff --git a/test/jdk/java/lang/invoke/RevealDirectTest.java b/test/jdk/java/lang/invoke/RevealDirectTest.java index d2f9f7d5e01..5e28db536c4 100644 --- a/test/jdk/java/lang/invoke/RevealDirectTest.java +++ b/test/jdk/java/lang/invoke/RevealDirectTest.java @@ -158,6 +158,10 @@ static class Nestmate { // CS methods have to be revealed with a matching lookupClass testOnMembersNoReveal("testCallerSensitiveNegative/2", mems, Simple.localLookup(), publicLookup()); testOnMembersNoReveal("testCallerSensitiveNegative/3", mems, Simple.localLookup(), Nestmate.localLookup()); + // CS methods have to have original access + Lookup lookup = Simple.localLookup().dropLookupMode(Lookup.ORIGINAL); + testOnMembersNoLookup("testCallerSensitiveNegative/4", mems, lookup); + testOnMembersNoReveal("testCallerSensitiveNegative/5", mems, Simple.localLookup(), lookup); } @Test public void testMethodHandleNatives() throws Throwable { if (VERBOSE) System.out.println("@Test testMethodHandleNatives"); diff --git a/test/jdk/java/lang/invoke/defineHiddenClass/HiddenNestmateTest.java b/test/jdk/java/lang/invoke/defineHiddenClass/HiddenNestmateTest.java index 7bba0090c0b..79668a1963f 100644 --- a/test/jdk/java/lang/invoke/defineHiddenClass/HiddenNestmateTest.java +++ b/test/jdk/java/lang/invoke/defineHiddenClass/HiddenNestmateTest.java @@ -72,6 +72,7 @@ public void hiddenClass() throws Throwable { Lookup lookup = MethodHandles.lookup().defineHiddenClass(bytes, false); Class c = lookup.lookupClass(); assertTrue(lookup.hasFullPrivilegeAccess()); + assertTrue((lookup.lookupModes() & ORIGINAL) == ORIGINAL); assertTrue(c.getNestHost() == c); // host of its own nest assertTrue(c.isHidden()); @@ -137,6 +138,8 @@ public void teleportToNestmate() throws Throwable { // Teleport to a hidden nestmate Lookup lc = MethodHandles.lookup().in(lookup.lookupClass()); assertTrue((lc.lookupModes() & PRIVATE) != 0); + assertTrue((lc.lookupModes() & ORIGINAL) == 0); + Lookup lc2 = lc.defineHiddenClass(bytes, false, NESTMATE); assertNestmate(lc2); } diff --git a/test/jdk/java/lang/invoke/modules/m3/jdk/test/ModuleAccessTest.java b/test/jdk/java/lang/invoke/modules/m3/jdk/test/ModuleAccessTest.java index c120aca323b..6a1e8efe103 100644 --- a/test/jdk/java/lang/invoke/modules/m3/jdk/test/ModuleAccessTest.java +++ b/test/jdk/java/lang/invoke/modules/m3/jdk/test/ModuleAccessTest.java @@ -91,7 +91,7 @@ public Object[][] samePackage() throws Exception { * * [A0] targetClass becomes the lookup class * [A1] no change in previous lookup class - * [A2] PROTECTED and PRIVATE are dropped + * [A2] PROTECTED, PRIVATE and ORIGINAL are dropped */ @Test(dataProvider = "samePackage") public void testLookupInSamePackage(Lookup lookup, Class targetClass) throws Exception { @@ -102,7 +102,7 @@ public void testLookupInSamePackage(Lookup lookup, Class targetClass) throws assertTrue(lookupClass.getModule() == targetClass.getModule()); assertTrue(lookup2.lookupClass() == targetClass); // [A0] assertTrue(lookup2.previousLookupClass() == lookup.previousLookupClass()); // [A1] - assertTrue(lookup2.lookupModes() == (lookup.lookupModes() & ~(PROTECTED|PRIVATE))); // [A2] + assertTrue(lookup2.lookupModes() == (lookup.lookupModes() & ~(PROTECTED|PRIVATE|ORIGINAL))); // [A2] } @DataProvider(name = "sameModule") @@ -119,7 +119,7 @@ public Object[][] sameModule() throws Exception { * * [A0] targetClass becomes the lookup class * [A1] no change in previous lookup class - * [A2] PROTECTED, PRIVATE and PACKAGE are dropped + * [A2] PROTECTED, PRIVATE, PACKAGE and ORIGINAL are dropped */ @Test(dataProvider = "sameModule") public void testLookupInSameModule(Lookup lookup, Class targetClass) throws Exception { @@ -130,7 +130,7 @@ public void testLookupInSameModule(Lookup lookup, Class targetClass) throws E assertTrue(lookupClass.getModule() == targetClass.getModule()); assertTrue(lookup2.lookupClass() == targetClass); // [A0] assertTrue(lookup2.previousLookupClass() == lookup.previousLookupClass()); // [A1] - assertTrue(lookup2.lookupModes() == (lookup.lookupModes() & ~(PROTECTED|PRIVATE|PACKAGE))); // [A2] + assertTrue(lookup2.lookupModes() == (lookup.lookupModes() & ~(PROTECTED|PRIVATE|PACKAGE|ORIGINAL))); // [A2] } @DataProvider(name = "anotherModule") @@ -148,7 +148,7 @@ public Object[][] anotherModule() throws Exception { * * [A0] targetClass becomes the lookup class * [A1] lookup class becomes previous lookup class - * [A2] PROTECTED, PRIVATE, PACKAGE, and MODULE are dropped + * [A2] PROTECTED, PRIVATE, PACKAGE, MODULE and ORIGINAL are dropped * [A3] no access to module internal types in m0 and m1 * [A4] if m1 reads m0, can access public types in m0; otherwise no access. * [A5] can access public types in m1 exported to m0 @@ -168,7 +168,7 @@ public void testLookupInAnotherModule(Lookup lookup, Class targetClass, Lookup lookup2 = lookup.in(targetClass); assertTrue(lookup2.lookupClass() == targetClass); // [A0] assertTrue(lookup2.previousLookupClass() == lookup.lookupClass()); // [A1] - assertTrue(lookup2.lookupModes() == (lookup.lookupModes() & ~(PROTECTED|PRIVATE|PACKAGE|MODULE))); // [A2] + assertTrue(lookup2.lookupModes() == (lookup.lookupModes() & ~(PROTECTED|PRIVATE|PACKAGE|MODULE|ORIGINAL))); // [A2] // [A3] no access to module internal type in m0 // [A4] if m1 reads m0, @@ -289,7 +289,7 @@ public void testLookupInThirdModule(Lookup lookup, Class c1, Class c2) thr Lookup lookup1 = lookup.in(c1); assertTrue(lookup1.lookupClass() == c1); assertTrue(lookup1.previousLookupClass() == c0); - assertTrue(lookup1.lookupModes() == (lookup.lookupModes() & ~(PROTECTED|PRIVATE|PACKAGE|MODULE))); + assertTrue(lookup1.lookupModes() == (lookup.lookupModes() & ~(PROTECTED|PRIVATE|PACKAGE|MODULE|ORIGINAL))); Lookup lookup2 = lookup1.in(c2); assertTrue(lookup2.lookupClass() == c2); // [A0] diff --git a/test/jdk/java/util/Collection/MOAT.java b/test/jdk/java/util/Collection/MOAT.java index a41ff7b5f18..ccaca2fc934 100644 --- a/test/jdk/java/util/Collection/MOAT.java +++ b/test/jdk/java/util/Collection/MOAT.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, 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 @@ -229,7 +229,16 @@ public static void realMain(String[] args) { List.of(1, 2, 3, 4, 5, 6, 7, 8), List.of(1, 2, 3, 4, 5, 6, 7, 8, 9), List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), - List.of(integerArray))) { + List.of(integerArray), + Stream.empty().toList(), + Stream.of(1).toList(), + Stream.of(1, 2).toList(), + Stream.of(1, 2, 3).toList(), + Stream.of(1, 2, 3, 4).toList(), + Stream.of((Integer)null).toList(), + Stream.of(1, null).toList(), + Stream.of(1, null, 3).toList(), + Stream.of(1, null, 3, 4).toList())) { testCollection(list); testImmutableList(list); testListMutatorsAlwaysThrow(list); @@ -1096,6 +1105,15 @@ private static void testList(final List l) { catch (UnsupportedOperationException ignored) {/* OK */} catch (Throwable t) { unexpected(t); } } + + int hashCode = 1; + for (Integer i : l) + hashCode = 31 * hashCode + (i == null ? 0 : i.hashCode()); + check(l.hashCode() == hashCode); + + var t = new ArrayList<>(l); + check(t.equals(l)); + check(l.equals(t)); } private static void testCollection(Collection c) { @@ -1131,6 +1149,13 @@ private static void testCollection1(Collection c) { if (c instanceof List) testList((List)c); + if (c instanceof Set) { + int hashCode = 0; + for (Integer i : c) + hashCode = hashCode + (i == null ? 0 : i.hashCode()); + check(c.hashCode() == hashCode); + } + check(supportsRemove(c)); try { @@ -1230,6 +1255,15 @@ private static void checkFunctionalInvariants(Map m) { private static void testMap(Map m) { System.out.println("\n==> " + m.getClass().getName()); + int hashCode = 0; + for (var e : m.entrySet()) { + int entryHash = (e.getKey() == null ? 0 : e.getKey().hashCode()) ^ + (e.getValue() == null ? 0 : e.getValue().hashCode()); + check(e.hashCode() == entryHash); + hashCode += entryHash; + } + check(m.hashCode() == hashCode); + if (m instanceof ConcurrentMap) testConcurrentMap((ConcurrentMap) m); diff --git a/test/jdk/java/util/List/ListFactories.java b/test/jdk/java/util/List/ListFactories.java index 280fe69aaf4..9b1d4a55150 100644 --- a/test/jdk/java/util/List/ListFactories.java +++ b/test/jdk/java/util/List/ListFactories.java @@ -33,6 +33,7 @@ import java.util.Iterator; import java.util.List; import java.util.ListIterator; +import java.util.stream.Stream; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -359,6 +360,19 @@ public void copyOfRejectsNullElements() { List list = List.copyOf(Arrays.asList(1, null, 3)); } + @Test(expectedExceptions=NullPointerException.class) + public void copyOfRejectsNullElements2() { + List list = List.copyOf(Stream.of("a", null, "c").toList()); + } + + @Test + public void copyOfCopiesNullAllowingList() { + List orig = Stream.of("a", "b", "c").toList(); + List copy = List.copyOf(orig); + + assertNotSame(orig, copy); + } + @Test public void iteratorShouldNotBeListIterator() { List list = List.of(1, 2, 3, 4, 5); diff --git a/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/ToListOpTest.java b/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/ToListOpTest.java new file mode 100644 index 00000000000..167110c5135 --- /dev/null +++ b/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/ToListOpTest.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2020, 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. + */ +package org.openjdk.tests.java.util.stream; + +import org.testng.annotations.Test; + +import java.util.*; +import java.util.stream.*; + +import static java.util.stream.LambdaTestHelpers.*; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + + +/** + * ToListOpTest + */ +@Test +public class ToListOpTest extends OpTestCase { + + public void testToList() { + assertCountSum(countTo(0).stream().toList(), 0, 0); + assertCountSum(countTo(10).stream().toList(), 10, 55); + } + + private void checkUnmodifiable(List list) { + try { + list.add(Integer.MIN_VALUE); + fail("List.add did not throw UnsupportedOperationException"); + } catch (UnsupportedOperationException ignore) { } + + if (list.size() > 0) { + try { + list.set(0, Integer.MAX_VALUE); + fail("List.set did not throw UnsupportedOperationException"); + } catch (UnsupportedOperationException ignore) { } + } + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testOps(String name, TestData.OfRef data) { + List objects = exerciseTerminalOps(data, s -> s.toList()); + checkUnmodifiable(objects); + assertFalse(objects.contains(null)); + } + + @Test(dataProvider = "withNull:StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testOpsWithNull(String name, TestData.OfRef data) { + List objects = exerciseTerminalOps(data, s -> s.toList()); + checkUnmodifiable(objects); + assertTrue(objects.contains(null)); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testDefaultOps(String name, TestData.OfRef data) { + List objects = exerciseTerminalOps(data, s -> DefaultMethodStreams.delegateTo(s).toList()); + checkUnmodifiable(objects); + assertFalse(objects.contains(null)); + } + + @Test(dataProvider = "withNull:StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testDefaultOpsWithNull(String name, TestData.OfRef data) { + List objects = exerciseTerminalOps(data, s -> DefaultMethodStreams.delegateTo(s).toList()); + checkUnmodifiable(objects); + assertTrue(objects.contains(null)); + } + +} diff --git a/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcClient.java b/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcClient.java index ad6a067ed47..91d1a8d1ead 100644 --- a/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcClient.java +++ b/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcClient.java @@ -24,11 +24,12 @@ import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; +import java.security.Security; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; -import jdk.test.lib.security.SecurityUtils; - /* * A JDK client process. */ @@ -161,7 +162,7 @@ public static void main(String[] args) throws Exception { String appProtocolsStr = System.getProperty(JdkProcUtils.PROP_APP_PROTOCOLS); // Re-enable TLSv1 and TLSv1.1 since client depends on them - SecurityUtils.removeFromDisabledTlsAlgs("TLSv1", "TLSv1.1"); + removeFromDisabledTlsAlgs("TLSv1", "TLSv1.1"); JdkClient.Builder builder = new JdkClient.Builder(); builder.setCertTuple(JdkProcUtils.createCertTuple( @@ -188,4 +189,22 @@ public static void main(String[] args) throws Exception { client.connect(host, port); } } + + /** + * Removes the specified protocols from the jdk.tls.disabledAlgorithms + * security property. + */ + private static void removeFromDisabledTlsAlgs(String... algs) { + List algList = Arrays.asList(algs); + String value = Security.getProperty("jdk.tls.disabledAlgorithms"); + StringBuilder newValue = new StringBuilder(); + for (String constraint : value.split(",")) { + String tmp = constraint.trim(); + if (!algList.contains(tmp)) { + newValue.append(tmp); + newValue.append(","); + } + } + Security.setProperty("jdk.tls.disabledAlgorithms", newValue.toString()); + } } diff --git a/test/jdk/javax/swing/JTable/4275046/bug4275046.java b/test/jdk/javax/swing/JTable/4275046/bug4275046.java new file mode 100644 index 00000000000..e6c647ae778 --- /dev/null +++ b/test/jdk/javax/swing/JTable/4275046/bug4275046.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2014, 2020, 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 + * @key headful + * @bug 4275046 + * @summary Tests editable combo box as a table editor. + * @run main bug4275046 + */ + +import java.awt.AWTException; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import javax.swing.DefaultCellEditor; +import javax.swing.SwingUtilities; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JTable; +import javax.swing.table.DefaultTableModel; + +public class bug4275046 { + + private static final String[] colNames = { "ID", "Color", "Stuff" }; + private static final Object[][] data = { { 1, "red", "abc"}, + { 2, "red", "def"}, + { 3, "red", "ghijk"} }; + + private static final String EXPECTED_VALUE = "rededited"; + + private JFrame frame; + private JTable table; + + private volatile Point tableLoc; + private volatile Rectangle cellRect; + + private volatile Object editedValue; + private volatile boolean testResult; + + private final Robot robot; + + public static void main(String[] args) throws Exception { + final bug4275046 test = new bug4275046(); + test.test(); + } + + public bug4275046() throws AWTException { + robot = new Robot(); + robot.setAutoDelay(100); + } + + private void createGUI() { + frame = new JFrame("bug4275046"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JComboBox cb = new JComboBox<>( + new Object[] {"blue", "yellow", "green", "red"}); + cb.setEditable(true); + DefaultCellEditor comboEditor = new DefaultCellEditor(cb); + comboEditor.setClickCountToStart(1); + + DefaultTableModel model = new DefaultTableModel(data, colNames); + table = new JTable(model); + table.getColumnModel().getColumn(1).setCellEditor(comboEditor); + + frame.add(table); + frame.pack(); + frame.setSize(550, 400); + frame.setVisible(true); + } + + private void test() throws Exception { + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + createGUI(); + } + }); + + runTest(); + checkResult(); + } finally { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + if (frame != null) { + frame.dispose(); + } + } + }); + } + } + + private void runTest() throws Exception { + robot.waitForIdle(); + + // Click the first cell in the "color" column + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + tableLoc = table.getLocationOnScreen(); + cellRect = table.getCellRect(0, 1, true); + } + }); + + robot.mouseMove(tableLoc.x + cellRect.x + cellRect.width / 2, + tableLoc.y + cellRect.y + cellRect.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + + // Edit the cell + robot.keyPress(KeyEvent.VK_E); + robot.keyRelease(KeyEvent.VK_E); + + robot.keyPress(KeyEvent.VK_D); + robot.keyRelease(KeyEvent.VK_D); + + robot.keyPress(KeyEvent.VK_I); + robot.keyRelease(KeyEvent.VK_I); + + robot.keyPress(KeyEvent.VK_T); + robot.keyRelease(KeyEvent.VK_T); + + robot.keyPress(KeyEvent.VK_E); + robot.keyRelease(KeyEvent.VK_E); + + robot.keyPress(KeyEvent.VK_D); + robot.keyRelease(KeyEvent.VK_D); + robot.delay(100); + + // Click another cell + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + cellRect = table.getCellRect(1, 2, true); + } + }); + + robot.mouseMove(tableLoc.x + cellRect.x + cellRect.width / 2, + tableLoc.y + cellRect.y + cellRect.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(100); + } + + private void checkResult() throws Exception { + robot.waitForIdle(); + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + // Read the edited value of from the cell + editedValue = table.getModel().getValueAt(0, 1); + System.out.println("The edited value is = " + editedValue); + testResult = editedValue.equals(EXPECTED_VALUE); + if (testResult) { + System.out.println("Test passed"); + } else { + System.out.println("Test failed"); + } + } + }); + if (!testResult) { + throw new RuntimeException("Expected value in the cell: '" + + EXPECTED_VALUE + "' but found '" + editedValue + "'."); + } + } +} diff --git a/test/jdk/jdk/jfr/api/consumer/recordingstream/TestOnMetadata.java b/test/jdk/jdk/jfr/api/consumer/recordingstream/TestOnMetadata.java new file mode 100644 index 00000000000..837b34a6132 --- /dev/null +++ b/test/jdk/jdk/jfr/api/consumer/recordingstream/TestOnMetadata.java @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jfr.api.consumer.recordingstream; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; + +import jdk.jfr.Event; +import jdk.jfr.EventType; +import jdk.jfr.FlightRecorder; +import jdk.jfr.Recording; +import jdk.jfr.Registered; +import jdk.jfr.consumer.EventStream; +import jdk.jfr.consumer.MetadataEvent; +import jdk.jfr.consumer.RecordingStream; + +/** + * @test + * @summary Tests RecordingStream::onMetadata(...) + * @key jfr + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.api.consumer.recordingstream.TestOnMetadata + */ +public class TestOnMetadata { + + public static void main(String... args) throws Throwable { + testDirectoryStream(true, false); + testFileStream(true, false); + + testAddAfterStart(); + testRemove(); + testNull(); + testUnmodifiable(); + } + + private static void testUnmodifiable() throws Exception { + AtomicBoolean fail = new AtomicBoolean(); + try (RecordingStream r = new RecordingStream()) { + r.onMetadata(m -> { + EventType t = FlightRecorder.getFlightRecorder().getEventTypes().get(0); + try { + m.getEventTypes().add(t); + System.out.println("Should not be able to modify getEventTypes()"); + fail.set(true); + } catch (UnsupportedOperationException uoe) { + // as expected; + } + try { + m.getRemovedEventTypes().add(t); + System.out.println("Should not be able to modify getRemovedEventTypes()"); + fail.set(true); + } catch (UnsupportedOperationException uoe) { + // as expected; + } + try { + m.getAddedEventTypes().add(t); + System.out.println("Should not be able to modify getAddedEventTypes()"); + fail.set(true); + } catch (UnsupportedOperationException uoe) { + // as expected; + } + r.close(); + }); + r.start(); + r.awaitTermination(); + if (fail.get()) { + throw new Exception("Metadata event could be mofified"); + } + } + } + + private static void testNull() throws Exception { + try (RecordingStream r = new RecordingStream()) { + try { + r.onMetadata(null); + throw new Exception("Expected NullPointerException"); + } catch (NullPointerException e) { + // as expected; + } + } + } + + private static void testRemove() throws Exception { + class RemoveEvent extends Event { + } + AtomicBoolean receviedMetadata = new AtomicBoolean(); + try (RecordingStream r = new RecordingStream()) { + Consumer m = e -> { + receviedMetadata.set(true); + }; + r.onMetadata(m); + r.remove(m); + r.onEvent(e -> { + r.close(); + }); + r.remove(m); + r.startAsync(); + RemoveEvent t = new RemoveEvent(); + t.commit(); + r.awaitTermination(); + if (receviedMetadata.get()) { + throw new Exception("Unexpected MetadataEvent!"); + } + } + } + + private static void testAddAfterStart() throws Exception { + try (RecordingStream rs = new RecordingStream()) { + rs.startAsync(); + rs.onMetadata(m -> { + }); + throw new Exception("Expected exception if handler is added after start"); + } catch (IllegalStateException ise) { + // as expected + } + } + + private static void testFileStream(boolean ordered, boolean reuse) throws Exception { + class Spider extends Event { + + } + AtomicInteger counter = new AtomicInteger(); + try (Recording rs = new Recording()) { + rs.start(); // event 1 + rotateChunk(); + FlightRecorder.register(Spider.class); + final EventType spiderType = EventType.getEventType(Spider.class); + // event 2 + rotateChunk(); + FlightRecorder.unregister(Spider.class); + // event 3 + rs.stop(); + Path p = Paths.get("test-file-stream-jfr"); + rs.dump(p); + try (EventStream s = EventStream.openFile(p)) { + System.out.println("Testing file: ordered=" + ordered + " reuse=" + reuse); + + s.setOrdered(ordered); + s.setReuse(reuse); + s.onMetadata(e -> { + int count = counter.get(); + if (count == 1) { + assertinitialEventypes(e); + } + if (count == 2) { + assertAddedEventType(e, spiderType); + } + if (count == 3) { + assertRemovedEventType(e, spiderType); + } + }); + s.start(); + if (counter.get() > 3) { + throw new Exception("Unexpected number of Metadata events"); + } + } + } + } + + private static void testDirectoryStream(boolean ordered, boolean reuse) throws Throwable { + @Registered(false) + class Turtle extends Event { + } + + class AssertEventTypes implements Consumer { + private final Semaphore semaphore = new Semaphore(0); + private volatile Throwable exception; + private volatile Consumer assertMethod; + + @Override + public void accept(MetadataEvent t) { + try { + assertMethod.accept(t); + } catch (Throwable e) { + this.exception = e; + e.printStackTrace(); + } + semaphore.release(); + } + + public void await() throws Throwable { + semaphore.acquire(); + if (exception != null) { + throw exception; + } + } + } + + try (RecordingStream rs = new RecordingStream()) { + System.out.println("Testing directory: ordered=" + ordered + " reuse=" + reuse); + rs.setOrdered(ordered); + rs.setReuse(reuse); + + AssertEventTypes assertion = new AssertEventTypes(); + + // Check initial event types + assertion.assertMethod = e -> assertinitialEventypes(e); + rs.onMetadata(assertion); + rs.startAsync(); + assertion.await(); + + // Check added event type + assertion.assertMethod = e -> assertAddedEventType(e, EventType.getEventType(Turtle.class)); + FlightRecorder.register(Turtle.class); + final EventType turtleType = EventType.getEventType(Turtle.class); + assertion.await(); + + // Check removal of turtle event + assertion.assertMethod = e -> assertRemovedEventType(e, turtleType); + FlightRecorder.unregister(Turtle.class); + rotateChunk(); + assertion.await(); + } + } + + private static void assertRemovedEventType(MetadataEvent m, EventType removedType) { + List eventTypes = FlightRecorder.getFlightRecorder().getEventTypes(); + List added = m.getAddedEventTypes(); + List all = m.getEventTypes(); + List removed = m.getRemovedEventTypes(); + + assertEventTypes(all, eventTypes); + assertEventTypes(added, Collections.emptyList()); + assertEventTypes(removed, List.of(removedType)); + } + + private static void assertAddedEventType(MetadataEvent m, EventType addedType) { + List eventTypes = FlightRecorder.getFlightRecorder().getEventTypes(); + List added = m.getAddedEventTypes(); + List all = m.getEventTypes(); + List removed = m.getRemovedEventTypes(); + + assertEventTypes(all, eventTypes); + assertEventTypes(added, List.of(addedType)); + assertEventTypes(removed, Collections.emptyList()); + } + + private static void assertinitialEventypes(MetadataEvent m) { + List added = m.getAddedEventTypes(); + List all = m.getEventTypes(); + List removed = m.getRemovedEventTypes(); + List eventTypes = FlightRecorder.getFlightRecorder().getEventTypes(); + + assertEventTypes(all, eventTypes); + assertEventTypes(added, eventTypes); + assertEventTypes(removed, Collections.emptyList()); + } + + private static void assertEventTypes(List eventTypes, List expected) { + if (eventTypes.size() != expected.size()) { + fail(eventTypes, expected); + } + Set set = new HashSet<>(); + for (EventType eb : expected) { + set.add(eb.getId()); + } + for (EventType ea : eventTypes) { + if (!set.contains(ea.getId())) { + fail(eventTypes, expected); + } + } + } + + private static void fail(List evenTypes, List expected) { + System.out.println("Event types don't match"); + System.out.println("Expected:"); + for (EventType t : expected) { + System.out.println(t.getName()); + } + System.out.println("Got:"); + for (EventType t : expected) { + System.out.println(t.getName()); + } + throw new RuntimeException("EventTypes don't match!"); + } + + private static void rotateChunk() { + try (Recording r = new Recording()) { + r.start(); + } + } +} diff --git a/test/jdk/jdk/jfr/jmx/streaming/TestClose.java b/test/jdk/jdk/jfr/jmx/streaming/TestClose.java new file mode 100644 index 00000000000..f21b6298641 --- /dev/null +++ b/test/jdk/jdk/jfr/jmx/streaming/TestClose.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jfr.jmx.streaming; + +import java.lang.management.ManagementFactory; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import javax.management.MBeanServerConnection; + +import jdk.jfr.Event; +import jdk.management.jfr.RemoteRecordingStream; + +/** + * @test + * @key jfr + * @summary Tests that a RemoteRecordingStream can be closed + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.jmx.streaming.TestClose + */ +public class TestClose { + + static class TestCloseEvent extends Event { + } + + public static void main(String... args) throws Exception { + MBeanServerConnection conn = ManagementFactory.getPlatformMBeanServer(); + Path p = Files.createDirectory(Paths.get("test-close-" + System.currentTimeMillis())); + + RemoteRecordingStream e = new RemoteRecordingStream(conn, p); + e.startAsync(); + // Produce enough to generate multiple chunks + for (int i = 0; i < 200_000; i++) { + TestCloseEvent event = new TestCloseEvent(); + event.commit(); + } + e.onFlush(() -> { + e.close(); // <- should clean up files. + }); + e.awaitTermination(); + int count = 0; + for (Object path : Files.list(p).toArray()) { + System.out.println(path); + count++; + } + if (count > 0) { + throw new Exception("Expected repository to be empty"); + } + } +} diff --git a/test/jdk/jdk/jfr/jmx/streaming/TestDelegated.java b/test/jdk/jdk/jfr/jmx/streaming/TestDelegated.java new file mode 100644 index 00000000000..9e204cd4c97 --- /dev/null +++ b/test/jdk/jdk/jfr/jmx/streaming/TestDelegated.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jfr.jmx.streaming; + +import java.lang.management.ManagementFactory; +import java.time.Duration; +import java.util.concurrent.CountDownLatch; + +import javax.management.MBeanServerConnection; + +import jdk.jfr.Event; +import jdk.management.jfr.RemoteRecordingStream; + +/** + * @test + * @key jfr + * @summary Sanity test methods that delegates to an ordinary stream + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.jmx.streaming.TestDelegated + */ +public class TestDelegated { + + private static MBeanServerConnection CONNECTION = ManagementFactory.getPlatformMBeanServer(); + + static class TestDelegatedEvent extends Event { + } + + // The assumption here is that the following methods don't + // need t be tested fully since they all delegate to the + // same implementation class that is tested elsewhere. + + public static void main(String[] args) throws Exception { + testRemove(); + testReuse(); + testOrdered(); + testOnEvent(); + testOnEventName(); + testOnFlush(); + testOnError(); + testOnClose(); + testSetMaxAge(); + testAwaitTermination(); + testAwaitTerminationWithDuration(); + } + + private static void testSetMaxAge() throws Exception { + try (RemoteRecordingStream stream = new RemoteRecordingStream(CONNECTION)) { + try { + stream.setMaxAge(null); + throw new Exception("Expected NullPointerException"); + } catch (NullPointerException npe) { + // As expected + } + } + } + + private static void testAwaitTerminationWithDuration() throws Exception { + try (RemoteRecordingStream rs = new RemoteRecordingStream(CONNECTION)) { + rs.onEvent(e -> { + rs.close(); + }); + rs.startAsync(); + TestDelegatedEvent e = new TestDelegatedEvent(); + e.commit(); + rs.awaitTermination(Duration.ofDays(1)); + } + } + + private static void testAwaitTermination() throws Exception { + try (RemoteRecordingStream rs = new RemoteRecordingStream(CONNECTION)) { + rs.onEvent(e -> { + rs.close(); + }); + rs.startAsync(); + TestDelegatedEvent e = new TestDelegatedEvent(); + e.commit(); + rs.awaitTermination(); + } + } + + private static void testOnClose() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + try (RemoteRecordingStream rs = new RemoteRecordingStream(CONNECTION)) { + rs.onClose(() -> { + latch.countDown(); + }); + rs.startAsync(); + rs.close(); + latch.await(); + } + } + + private static void testOnError() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + try (RemoteRecordingStream rs = new RemoteRecordingStream(CONNECTION)) { + rs.onEvent(TestDelegatedEvent.class.getName(), e -> { + throw new RuntimeException("Testing"); + }); + rs.onError(t -> { + latch.countDown(); + }); + rs.startAsync(); + TestDelegatedEvent e = new TestDelegatedEvent(); + e.commit(); + latch.await(); + } + } + + private static void testOnFlush() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + try (RemoteRecordingStream rs = new RemoteRecordingStream(CONNECTION)) { + rs.onFlush(() -> { + latch.countDown(); + }); + rs.startAsync(); + TestDelegatedEvent e = new TestDelegatedEvent(); + e.commit(); + latch.await(); + } + } + + private static void testOnEventName() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + try (RemoteRecordingStream rs = new RemoteRecordingStream(CONNECTION)) { + rs.onEvent(TestDelegatedEvent.class.getName(), e -> { + latch.countDown(); + }); + rs.startAsync(); + TestDelegatedEvent e = new TestDelegatedEvent(); + e.commit(); + latch.await(); + } + } + + private static void testOnEvent() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + try (RemoteRecordingStream rs = new RemoteRecordingStream(CONNECTION)) { + rs.onEvent(e -> { + System.out.println(e); + latch.countDown(); + }); + rs.startAsync(); + TestDelegatedEvent e = new TestDelegatedEvent(); + e.commit(); + latch.await(); + } + + } + + private static void testOrdered() throws Exception { + try (RemoteRecordingStream rs = new RemoteRecordingStream(CONNECTION)) { + rs.setOrdered(true); + rs.setOrdered(false); + } + } + + private static void testReuse() throws Exception { + try (RemoteRecordingStream rs = new RemoteRecordingStream(CONNECTION)) { + rs.setReuse(true); + rs.setReuse(false); + } + } + + private static void testRemove() throws Exception { + try (RemoteRecordingStream rs = new RemoteRecordingStream(CONNECTION)) { + Runnable r1 = () -> { + }; + Runnable r2 = () -> { + }; + rs.onFlush(r1); + if (!rs.remove(r1)) { + throw new Exception("Expected remove to return true"); + } + if (rs.remove(r2)) { + throw new Exception("Expected remove to return false"); + } + } + } +} diff --git a/test/jdk/jdk/jfr/jmx/streaming/TestEnableDisable.java b/test/jdk/jdk/jfr/jmx/streaming/TestEnableDisable.java new file mode 100644 index 00000000000..d8459924577 --- /dev/null +++ b/test/jdk/jdk/jfr/jmx/streaming/TestEnableDisable.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jfr.jmx.streaming; + +import java.lang.management.ManagementFactory; +import java.util.concurrent.CountDownLatch; + +import javax.management.MBeanServerConnection; + +import jdk.jfr.Enabled; +import jdk.jfr.Event; +import jdk.jfr.Name; + +import jdk.management.jfr.RemoteRecordingStream; + +/** + * @test + * @key jfr + * @summary Tests that event settings for a RemoteRecordingStream can be changed + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.jmx.streaming.TestEnableDisable + */ +public class TestEnableDisable { + @Name("Zebra") + @Enabled(false) + static class Zebra extends Event { + } + + @Name("Tiger") + @Enabled(true) + static class Tiger extends Event { + } + + public static void main(String... args) throws Exception { + CountDownLatch zebraLatch = new CountDownLatch(1); + MBeanServerConnection conn = ManagementFactory.getPlatformMBeanServer(); + try (RemoteRecordingStream stream = new RemoteRecordingStream(conn)) { + stream.enable("Zebra"); + stream.disable("Tiger"); + + stream.onEvent("Zebra", e -> { + System.out.println(e); + zebraLatch.countDown(); + }); + stream.onEvent("Tiger", e -> { + System.out.println(e); + throw new RuntimeException("Unexpected Tiger"); // will close stream + }); + + stream.startAsync(); + + Tiger t = new Tiger(); + t.commit(); + + Zebra z = new Zebra(); + z.commit(); + + zebraLatch.await(); + } + + } +} diff --git a/test/jdk/jdk/jfr/jmx/streaming/TestMaxSize.java b/test/jdk/jdk/jfr/jmx/streaming/TestMaxSize.java new file mode 100644 index 00000000000..23bb05e5016 --- /dev/null +++ b/test/jdk/jdk/jfr/jmx/streaming/TestMaxSize.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jfr.jmx.streaming; + +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.management.MBeanServerConnection; + +import jdk.jfr.Event; +import jdk.management.jfr.RemoteRecordingStream; + +/** + * @test + * @key jfr + * @summary Tests that max size can be set for a RemoteRecordingStream + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.jmx.streaming.TestMaxSize + */ +public class TestMaxSize { + + static class Monkey extends Event { + } + + public static void main(String... args) throws Exception { + MBeanServerConnection conn = ManagementFactory.getPlatformMBeanServer(); + Path dir = Files.createDirectories(Paths.get("max-size-" + System.currentTimeMillis())); + System.out.println(dir); + AtomicBoolean finished = new AtomicBoolean(); + try (RemoteRecordingStream e = new RemoteRecordingStream(conn, dir)) { + e.startAsync(); + e.onEvent(ev -> { + if (finished.get()) { + return; + } + // Consume some events, but give back control + // to stream so it can be closed. + try { + Thread.sleep(10); + } catch (InterruptedException e1) { + // ignore + } + }); + while (directorySize(dir) < 50_000_000) { + emitEvents(500_000); + } + e.setMaxSize(1_000_000); + long count = fileCount(dir); + if (count > 2) { + // Two chunks can happen when header of new chunk is written and previous + // chunk is not finalized. + throw new Exception("Expected only one or two chunks with setMaxSize(1_000_000). Found " + count); + } + finished.set(true); + } + } + + private static void emitEvents(int count) throws InterruptedException { + for (int i = 0; i < count; i++) { + Monkey m = new Monkey(); + m.commit(); + } + System.out.println("Emitted " + count + " events"); + Thread.sleep(1000); + } + + private static int fileCount(Path dir) throws IOException { + System.out.println("Files:"); + AtomicInteger count = new AtomicInteger(); + Files.list(dir).forEach(p -> { + System.out.println(p); + count.incrementAndGet(); + }); + return count.get(); + } + + private static long directorySize(Path dir) throws IOException { + long p = Files.list(dir).mapToLong(f -> { + try { + return Files.size(f); + } catch (IOException e) { + return 0; + } + }).sum(); + System.out.println("Directory size: " + p); + return p; + } +} diff --git a/test/jdk/jdk/jfr/jmx/streaming/TestMultipleChunks.java b/test/jdk/jdk/jfr/jmx/streaming/TestMultipleChunks.java new file mode 100644 index 00000000000..ff89b09ab5e --- /dev/null +++ b/test/jdk/jdk/jfr/jmx/streaming/TestMultipleChunks.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jfr.jmx.streaming; + +import java.lang.management.ManagementFactory; +import java.util.concurrent.CountDownLatch; + +import javax.management.MBeanServerConnection; + +import jdk.jfr.Event; +import jdk.jfr.Recording; +import jdk.management.jfr.RemoteRecordingStream; + +/** + * @test + * @key jfr + * @summary Tests that a RemoteRecordingStream can stream over multiple chunks + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.jmx.streaming.TestMultipleChunks + */ +public class TestMultipleChunks { + + static class Snake extends Event { + } + + public static void main(String... args) throws Exception { + CountDownLatch latch = new CountDownLatch(5); + MBeanServerConnection conn = ManagementFactory.getPlatformMBeanServer(); + try (RemoteRecordingStream s = new RemoteRecordingStream(conn)) { + s.onEvent(e -> latch.countDown()); + s.startAsync(); + for (int i = 0; i < 5; i++) { + Snake snake = new Snake(); + snake.commit(); + rotate(); + } + } + } + + private static void rotate() { + try (Recording r = new Recording()) { + r.start(); + } + } +} diff --git a/test/jdk/jdk/jfr/jmx/streaming/TestNew.java b/test/jdk/jdk/jfr/jmx/streaming/TestNew.java new file mode 100644 index 00000000000..d23911e21e1 --- /dev/null +++ b/test/jdk/jdk/jfr/jmx/streaming/TestNew.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jfr.jmx.streaming; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.lang.management.ManagementFactory; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; + +import jdk.management.jfr.FlightRecorderMXBean; +import jdk.management.jfr.RemoteRecordingStream; + +/** + * @test + * @key jfr + * @summary Test constructors of RemoteRecordingStream + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.jmx.streaming.TestNew + */ +public class TestNew { + + private final static ObjectName MXBEAN = createObjectName(); + + public static void main(String... args) throws Exception { + testNullArguments(); + testMissingDirectory(); + testNotDirectory(); + testDefaultDIrectory(); + TestUserDefinedDirectory(); + + testMissingFlightRecorderMXBean(); + } + + private static void TestUserDefinedDirectory() throws IOException { + Path p = Paths.get("user-repository-" + System.currentTimeMillis()); + Files.createDirectory(p); + MBeanServerConnection conn = ManagementFactory.getPlatformMBeanServer(); + try (RemoteRecordingStream s = new RemoteRecordingStream(conn, p)) { + // success + } + } + + private static void testDefaultDIrectory() throws IOException { + MBeanServerConnection conn = ManagementFactory.getPlatformMBeanServer(); + try (RemoteRecordingStream s = new RemoteRecordingStream(conn)) { + // success + } + } + + private static void testNotDirectory() throws Exception { + Path p = Paths.get("file.txt"); + RandomAccessFile raf = new RandomAccessFile(p.toFile(), "rw"); + raf.close(); + MBeanServerConnection conn = ManagementFactory.getPlatformMBeanServer(); + try (var s = new RemoteRecordingStream(conn, p)) { + throw new Exception("Expected IOException"); + } catch (IOException ioe) { + if (!ioe.getMessage().contains("Download location must be a directory")) { + throw new Exception("Unexpected message " + ioe.getMessage()); + } + } + } + + private static void testMissingDirectory() throws Exception { + Path p = Paths.get("/missing"); + MBeanServerConnection conn = ManagementFactory.getPlatformMBeanServer(); + try (var s = new RemoteRecordingStream(conn, p)) { + throw new Exception("Expected IOException"); + } catch (IOException ioe) { + if (!ioe.getMessage().contains("Download directory doesn't exist")) { + throw new Exception("Unexpected message " + ioe.getMessage()); + } + } + } + + private static void testNullArguments() throws Exception { + try (var s = new RemoteRecordingStream(null)) { + throw new Exception("Expected NullPointerException"); + } catch (NullPointerException npe) { + // as expected + } + MBeanServerConnection conn = ManagementFactory.getPlatformMBeanServer(); + try (var s = new RemoteRecordingStream(conn, null)) { + throw new Exception("Expected NullPointerException"); + } catch (NullPointerException npe) { + // as expected + } + } + + private static void testMissingFlightRecorderMXBean() throws Exception { + + MBeanServerConnection conn = ManagementFactory.getPlatformMBeanServer(); + conn.unregisterMBean(MXBEAN); + try (var s = new RemoteRecordingStream(conn)) { + throw new Exception("Expected IOException"); + } catch (IOException npe) { + // as expected + } + } + + private static ObjectName createObjectName() { + try { + return new ObjectName(FlightRecorderMXBean.MXBEAN_NAME); + } catch (Exception e) { + throw new InternalError("Unexpected exception", e); + } + } +} diff --git a/test/jdk/jdk/jfr/jmx/streaming/TestRotate.java b/test/jdk/jdk/jfr/jmx/streaming/TestRotate.java new file mode 100644 index 00000000000..05a0bab74da --- /dev/null +++ b/test/jdk/jdk/jfr/jmx/streaming/TestRotate.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jfr.jmx.streaming; + +import java.lang.management.ManagementFactory; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.concurrent.CountDownLatch; + +import javax.management.MBeanServerConnection; + +import jdk.jfr.Event; +import jdk.jfr.Recording; +import jdk.jfr.StackTrace; +import jdk.management.jfr.RemoteRecordingStream; + +/** + * @test + * @key jfr + * @summary Tests that streaming can work over chunk rotations + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.jmx.streaming.TestRotate + */ +public class TestRotate { + + @StackTrace(false) + static class TestRotateEvent extends Event { + int value; + } + + public static void main(String... args) throws Exception { + MBeanServerConnection conn = ManagementFactory.getPlatformMBeanServer(); + Path p = Files.createDirectory(Paths.get("test-stream-rotate-" + System.currentTimeMillis())); + CountDownLatch latch = new CountDownLatch(100); + try (RemoteRecordingStream r = new RemoteRecordingStream(conn, p)) { + r.onEvent(e -> { + System.out.println(e); + latch.countDown(); + }); + r.startAsync(); + for (int i = 1; i <= 100; i++) { + TestRotateEvent e = new TestRotateEvent(); + e.value = i; + e.commit(); + if (i % 30 == 0) { + rotate(); + } + Thread.sleep(10); + } + System.out.println("Events generated. Awaiting consumption"); + latch.await(); + } + } + + private static void rotate() { + try (Recording r = new Recording()) { + r.start(); + } + } +} diff --git a/test/jdk/jdk/jfr/jmx/streaming/TestSetSettings.java b/test/jdk/jdk/jfr/jmx/streaming/TestSetSettings.java new file mode 100644 index 00000000000..667ae5c8d5b --- /dev/null +++ b/test/jdk/jdk/jfr/jmx/streaming/TestSetSettings.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jfr.jmx.streaming; + +import java.lang.management.ManagementFactory; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CountDownLatch; + +import javax.management.MBeanServerConnection; + +import jdk.jfr.Enabled; +import jdk.jfr.Event; +import jdk.jfr.Name; +import jdk.jfr.StackTrace; +import jdk.management.jfr.RemoteRecordingStream; + +/** + * @test + * @key jfr + * @summary Tests that a RemoteRecordingStream can be configured using + * setSettings + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.jmx.streaming.TestSetSettings + */ +public class TestSetSettings { + + @Enabled(false) + @StackTrace(false) + @Name("Event1") + static class Event1 extends Event { + } + + @Enabled(false) + @StackTrace(false) + @Name("Event2") + static class Event2 extends Event { + } + + public static void main(String... args) throws Exception { + CountDownLatch latch1 = new CountDownLatch(1); + CountDownLatch latch2 = new CountDownLatch(1); + + MBeanServerConnection conn = ManagementFactory.getPlatformMBeanServer(); + try (RemoteRecordingStream r = new RemoteRecordingStream(conn)) { + r.onEvent("Event1", e -> { + System.out.println("Found event: " + e.getEventType().getName()); + if (e.getStackTrace() == null) { + System.out.println("Missing strack trace"); + return; + } + latch1.countDown(); + }); + r.onEvent("Event2", e -> { + System.out.println("Found event: " + e.getEventType().getName()); + if (e.getStackTrace() == null) { + System.out.println("Missing strack trace"); + return; + } + latch2.countDown(); + }); + // Set settings before start + Map settings = new HashMap<>(); + settings.put("Event1#enabled", "true"); + settings.put("Event1#stackTrace", "true"); + r.setSettings(settings); + + r.startAsync(); + + Event1 e1 = new Event1(); + e1.commit(); + System.out.println("Awaiting latch 1"); + latch1.await(); + + // Set settings when running + settings = new HashMap<>(); + settings.put("Event2#enabled", "true"); + settings.put("Event2#stackTrace", "true"); + r.setSettings(settings); + Event2 e2 = new Event2(); + e2.commit(); + System.out.println("Awaiting latch 2"); + latch2.await(); + } + } +} diff --git a/test/jdk/jdk/nio/zipfs/TestLocOffsetFromZip64EF.java b/test/jdk/jdk/nio/zipfs/TestLocOffsetFromZip64EF.java index f38aa0d0629..60fea1b9ac9 100644 --- a/test/jdk/jdk/nio/zipfs/TestLocOffsetFromZip64EF.java +++ b/test/jdk/jdk/nio/zipfs/TestLocOffsetFromZip64EF.java @@ -24,10 +24,12 @@ import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.io.*; import java.nio.charset.StandardCharsets; +import java.nio.file.FileSystem; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.util.List; @@ -38,7 +40,7 @@ /** * @test - * @bug 8255380 + * @bug 8255380 8257445 * @summary Test that Zip FS can access the LOC offset from the Zip64 extra field * @modules jdk.zipfs * @requires (os.family == "linux") | (os.family == "mac") @@ -91,14 +93,29 @@ public static void createZipWithZip64Ext() { rc.assertSuccess(); } + /* + * DataProvider used to verify that a Zip file that contains a Zip64 Extra + * (EXT) header can be traversed + */ + @DataProvider(name = "zipInfoTimeMap") + protected Object[][] zipInfoTimeMap() { + return new Object[][]{ + {Map.of()}, + {Map.of("zipinfo-time", "False")}, + {Map.of("zipinfo-time", "true")}, + {Map.of("zipinfo-time", "false")} + }; + } + /** * Navigate through the Zip file entries using Zip FS + * @param env Zip FS properties to use when accessing the Zip file * @throws IOException if an error occurs */ - @Test - public void walkZipFSTest() throws IOException { + @Test(dataProvider = "zipInfoTimeMap") + public void walkZipFSTest(final Map env) throws IOException { try (FileSystem fs = - FileSystems.newFileSystem(Paths.get(ZIP_FILE_NAME), Map.of("zipinfo-time", "False"))) { + FileSystems.newFileSystem(Paths.get(ZIP_FILE_NAME), env)) { for (Path root : fs.getRootDirectories()) { Files.walkFileTree(root, new SimpleFileVisitor<>() { @Override diff --git a/test/micro/org/openjdk/bench/java/lang/invoke/LookupDefineClass.java b/test/micro/org/openjdk/bench/java/lang/invoke/LookupDefineClass.java index 1b7e467e8a5..5ae02aa204d 100644 --- a/test/micro/org/openjdk/bench/java/lang/invoke/LookupDefineClass.java +++ b/test/micro/org/openjdk/bench/java/lang/invoke/LookupDefineClass.java @@ -230,7 +230,7 @@ public static class UnsafeAnonymousClass { private static final MethodHandles.Lookup lookup = defineHostClass(new Loader("anonymous-class-loader"),"foo.AnonymousHost", FOO_HOST_BYTES); - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") @Benchmark public Class load() throws ClassNotFoundException { return unsafe.defineAnonymousClass(lookup.lookupClass(), X_BYTECODE, null);